Action what; int fd; int new_fd; char* path; int flags;
mode_t mode;
voidDo() { if (what == kOpen) {
fd = open(path, flags, mode); if (fd == -1) _exit(127); // If it didn't land where we wanted it, move it. if (fd != new_fd) { if (dup2(fd, new_fd) == -1) _exit(127);
close(fd);
}
} elseif (what == kClose) { // Failure to close is ignored.
close(fd);
} elseif (what == kChdir) { if (chdir(path) == -1) _exit(127);
} elseif (what == kFchdir) { if (fchdir(fd) == -1) _exit(127);
} else { // It's a dup2. if (fd == new_fd) { // dup2(2) is a no-op if fd == new_fd, but POSIX suggests that we should // manually remove the O_CLOEXEC flag in that case (because otherwise // what use is the dup?). // See https://www.austingroupbugs.net/view.php?id=411 for details. int flags = fcntl(fd, F_GETFD, 0); if (flags == -1 || fcntl(fd, F_SETFD, flags & ~FD_CLOEXEC) == -1) _exit(127);
} else { if (dup2(fd, new_fd) == -1) _exit(127);
}
}
}
};
struct __posix_spawnattr { short flags;
pid_t pgroup;
sched_param schedparam; int schedpolicy; union {
sigset_t sigset;
sigset64_t sigset64;
} sigmask, sigdefault;
};
staticvoid ApplyAttrs(short flags, const posix_spawnattr_t* attr) { // POSIX: "If POSIX_SPAWN_SETSIGDEF is set ... signals in sigdefault ... // shall be set to their default actions in the child process." // POSIX: "Signals set to be caught by the calling process shall be // set to the default action in the child process." bool use_sigdefault = ((flags & POSIX_SPAWN_SETSIGDEF) != 0); conststruct sigaction64 default_sa = { .sa_handler = SIG_DFL }; for (int s = 1; s < _NSIG; ++s) { bool reset = false; if (use_sigdefault && sigismember64(&(*attr)->sigdefault.sigset64, s)) {
reset = true;
} else { struct sigaction64 current; if (sigaction64(s, nullptr, ¤t) == -1) _exit(127);
reset = (current.sa_handler != SIG_IGN && current.sa_handler != SIG_DFL);
} if (reset && sigaction64(s, &default_sa, nullptr) == -1) _exit(127);
}
// POSIX_SPAWN_SETSCHEDULER overrides POSIX_SPAWN_SETSCHEDPARAM, but it is not an error // to set both. if ((flags & POSIX_SPAWN_SETSCHEDULER) != 0) { if (sched_setscheduler(0, (*attr)->schedpolicy, &(*attr)->schedparam) == -1) _exit(127);
} elseif ((flags & POSIX_SPAWN_SETSCHEDPARAM) != 0) { if (sched_setparam(0, &(*attr)->schedparam) == -1) _exit(127);
}
if ((flags & POSIX_SPAWN_RESETIDS) != 0) { if (seteuid(getuid()) == -1 || setegid(getgid()) == -1) _exit(127);
}
if ((flags & POSIX_SPAWN_SETSIGMASK) != 0) { if (sigprocmask64(SIG_SETMASK, &(*attr)->sigmask.sigset64, nullptr)) _exit(127);
}
if ((flags & POSIX_SPAWN_CLOEXEC_DEFAULT) != 0) { // mark all open fds except stdin/out/err as close-on-exec if (close_range(3, ~0U, CLOSE_RANGE_CLOEXEC)) _exit(127);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.