diff options
-rw-r--r-- | src/basic/process-util.c | 46 | ||||
-rw-r--r-- | src/basic/process-util.h | 12 | ||||
-rw-r--r-- | src/home/homed-home.c | 1 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/bus-socket.c | 5 | ||||
-rw-r--r-- | src/login/logind-brightness.c | 2 | ||||
-rw-r--r-- | src/resolve/test-resolved-stream.c | 6 | ||||
-rw-r--r-- | src/shared/dissect-image.c | 3 | ||||
-rw-r--r-- | src/shared/elf-util.c | 1 | ||||
-rw-r--r-- | src/shared/exec-util.c | 1 | ||||
-rw-r--r-- | src/shared/pager.c | 2 | ||||
-rw-r--r-- | src/shutdown/umount.c | 10 | ||||
-rw-r--r-- | src/test/test-process-util.c | 2 |
12 files changed, 63 insertions, 28 deletions
diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 4df369dd2a..919387f958 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -1134,6 +1134,7 @@ static void restore_sigsetp(sigset_t **ssp) { int safe_fork_full( const char *name, + const int stdio_fds[3], const int except_fds[], size_t n_except_fds, ForkFlags flags, @@ -1292,6 +1293,27 @@ int safe_fork_full( } } + if (flags & FORK_REARRANGE_STDIO) { + if (stdio_fds) { + r = rearrange_stdio(stdio_fds[0], stdio_fds[1], stdio_fds[2]); + if (r < 0) { + log_full_errno(prio, r, "Failed to rearrange stdio fds: %m"); + _exit(EXIT_FAILURE); + } + } else { + r = make_null_stdio(); + if (r < 0) { + log_full_errno(prio, r, "Failed to connect stdin/stdout to /dev/null: %m"); + _exit(EXIT_FAILURE); + } + } + } else if (flags & FORK_STDOUT_TO_STDERR) { + if (dup2(STDERR_FILENO, STDOUT_FILENO) < 0) { + log_full_errno(prio, errno, "Failed to connect stdout to stderr: %m"); + _exit(EXIT_FAILURE); + } + } + if (flags & FORK_CLOSE_ALL_FDS) { /* Close the logs here in case it got reopened above, as close_all_fds() would close them for us */ log_close(); @@ -1317,20 +1339,6 @@ int safe_fork_full( log_set_open_when_needed(false); } - if (flags & FORK_NULL_STDIO) { - r = make_null_stdio(); - if (r < 0) { - log_full_errno(prio, r, "Failed to connect stdin/stdout to /dev/null: %m"); - _exit(EXIT_FAILURE); - } - - } else if (flags & FORK_STDOUT_TO_STDERR) { - if (dup2(STDERR_FILENO, STDOUT_FILENO) < 0) { - log_full_errno(prio, errno, "Failed to connect stdout to stderr: %m"); - _exit(EXIT_FAILURE); - } - } - if (flags & FORK_RLIMIT_NOFILE_SAFE) { r = rlimit_nofile_safe(); if (r < 0) { @@ -1364,7 +1372,10 @@ int namespace_fork( * process. This ensures that we are fully a member of the destination namespace, with pidns an all, so that * /proc/self/fd works correctly. */ - r = safe_fork_full(outer_name, except_fds, n_except_fds, (flags|FORK_DEATHSIG) & ~(FORK_REOPEN_LOG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE), ret_pid); + r = safe_fork_full(outer_name, + NULL, + except_fds, n_except_fds, + (flags|FORK_DEATHSIG) & ~(FORK_REOPEN_LOG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE), ret_pid); if (r < 0) return r; if (r == 0) { @@ -1379,7 +1390,10 @@ int namespace_fork( } /* We mask a few flags here that either make no sense for the grandchild, or that we don't have to do again */ - r = safe_fork_full(inner_name, except_fds, n_except_fds, flags & ~(FORK_WAIT|FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_NULL_STDIO), &pid); + r = safe_fork_full(inner_name, + NULL, + except_fds, n_except_fds, + flags & ~(FORK_WAIT|FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REARRANGE_STDIO), &pid); if (r < 0) _exit(EXIT_FAILURE); if (r == 0) { diff --git a/src/basic/process-util.h b/src/basic/process-util.h index 279f5d6e6b..6f6fc7d94e 100644 --- a/src/basic/process-util.h +++ b/src/basic/process-util.h @@ -143,7 +143,7 @@ typedef enum ForkFlags { FORK_CLOSE_ALL_FDS = 1 << 1, /* Close all open file descriptors in the child, except for 0,1,2 */ FORK_DEATHSIG = 1 << 2, /* Set PR_DEATHSIG in the child to SIGTERM */ FORK_DEATHSIG_SIGINT = 1 << 3, /* Set PR_DEATHSIG in the child to SIGINT */ - FORK_NULL_STDIO = 1 << 4, /* Connect 0,1,2 to /dev/null */ + FORK_REARRANGE_STDIO = 1 << 4, /* Connect 0,1,2 to specified fds or /dev/null */ FORK_REOPEN_LOG = 1 << 5, /* Reopen log connection */ FORK_LOG = 1 << 6, /* Log above LOG_DEBUG log level about failures */ FORK_WAIT = 1 << 7, /* Wait until child exited */ @@ -157,10 +157,16 @@ typedef enum ForkFlags { FORK_CLOEXEC_OFF = 1 << 15, /* In the child: turn off O_CLOEXEC on all fds in except_fds[] */ } ForkFlags; -int safe_fork_full(const char *name, const int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid); +int safe_fork_full( + const char *name, + const int stdio_fds[3], + const int except_fds[], + size_t n_except_fds, + ForkFlags flags, + pid_t *ret_pid); static inline int safe_fork(const char *name, ForkFlags flags, pid_t *ret_pid) { - return safe_fork_full(name, NULL, 0, flags, ret_pid); + return safe_fork_full(name, NULL, NULL, 0, flags, ret_pid); } int namespace_fork(const char *outer_name, const char *inner_name, const int except_fds[], size_t n_except_fds, ForkFlags flags, int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd, pid_t *ret_pid); diff --git a/src/home/homed-home.c b/src/home/homed-home.c index e6b7740600..8b4a81d7e8 100644 --- a/src/home/homed-home.c +++ b/src/home/homed-home.c @@ -1180,6 +1180,7 @@ static int home_start_work(Home *h, const char *verb, UserRecord *hr, UserRecord return -errno; r = safe_fork_full("(sd-homework)", + NULL, (int[]) { stdin_fd, stdout_fd }, 2, FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_LOG|FORK_REOPEN_LOG, &pid); if (r < 0) diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c index 64037e4fe0..aca049b052 100644 --- a/src/libsystemd/sd-bus/bus-socket.c +++ b/src/libsystemd/sd-bus/bus-socket.c @@ -994,7 +994,10 @@ int bus_socket_exec(sd_bus *b) { if (r < 0) return -errno; - r = safe_fork_full("(sd-busexec)", s+1, 1, FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE, &b->busexec_pid); + r = safe_fork_full("(sd-busexec)", + NULL, + s+1, 1, + FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE, &b->busexec_pid); if (r < 0) { safe_close_pair(s); return r; diff --git a/src/login/logind-brightness.c b/src/login/logind-brightness.c index 21feaae0c3..d238cb74c9 100644 --- a/src/login/logind-brightness.c +++ b/src/login/logind-brightness.c @@ -136,7 +136,7 @@ static int brightness_writer_fork(BrightnessWriter *w) { assert(w->child == 0); assert(!w->child_event_source); - r = safe_fork("(sd-bright)", FORK_DEATHSIG|FORK_NULL_STDIO|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &w->child); + r = safe_fork("(sd-bright)", FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &w->child); if (r < 0) return r; if (r == 0) { diff --git a/src/resolve/test-resolved-stream.c b/src/resolve/test-resolved-stream.c index c708eb4da8..d7fe3c42f5 100644 --- a/src/resolve/test-resolved-stream.c +++ b/src/resolve/test-resolved-stream.c @@ -147,8 +147,10 @@ static void *tls_dns_server(void *p) { fd_tls = fd[1]; } - r = safe_fork_full("(test-resolved-stream-tls-openssl)", (int[]) { fd_server, fd_tls }, 2, - FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_LOG|FORK_REOPEN_LOG, &openssl_pid); + r = safe_fork_full("(test-resolved-stream-tls-openssl)", + NULL, + (int[]) { fd_server, fd_tls }, 2, + FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_LOG|FORK_REOPEN_LOG, &openssl_pid); assert_se(r >= 0); if (r == 0) { /* Child */ diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 9a4bac99a1..ce37dd31ce 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -1436,8 +1436,9 @@ static int run_fsck(int node_fd, const char *fstype) { r = safe_fork_full( "(fsck)", + NULL, &node_fd, 1, /* Leave the node fd open */ - FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_NULL_STDIO|FORK_CLOEXEC_OFF, + FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_CLOEXEC_OFF, &pid); if (r < 0) return log_debug_errno(r, "Failed to fork off fsck: %m"); diff --git a/src/shared/elf-util.c b/src/shared/elf-util.c index 8da16f528f..98c47d9125 100644 --- a/src/shared/elf-util.c +++ b/src/shared/elf-util.c @@ -784,6 +784,7 @@ int parse_elf_object(int fd, const char *executable, bool fork_disable_dump, cha * system call or interacting with the system in any way, besides reading from * the file descriptor and writing into these four pipes. */ r = safe_fork_full("(sd-parse-elf)", + NULL, (int[]){ fd, error_pipe[1], return_pipe[1], json_pipe[1] }, 4, FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_NEW_USERNS|FORK_WAIT|FORK_REOPEN_LOG, diff --git a/src/shared/exec-util.c b/src/shared/exec-util.c index 2e8f5b8562..40e9342cd5 100644 --- a/src/shared/exec-util.c +++ b/src/shared/exec-util.c @@ -487,6 +487,7 @@ int fork_agent(const char *name, const int except[], size_t n_except, pid_t *ret /* Spawns a temporary TTY agent, making sure it goes away when we go away */ r = safe_fork_full(name, + NULL, except, n_except, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_RLIMIT_NOFILE_SAFE, diff --git a/src/shared/pager.c b/src/shared/pager.c index 6ed35a3ca9..7bede85752 100644 --- a/src/shared/pager.c +++ b/src/shared/pager.c @@ -316,7 +316,7 @@ int show_man_page(const char *desc, bool null_stdio) { } else args[1] = desc; - r = safe_fork("(man)", FORK_RESET_SIGNALS|FORK_DEATHSIG|(null_stdio ? FORK_NULL_STDIO : 0)|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid); + r = safe_fork("(man)", FORK_RESET_SIGNALS|FORK_DEATHSIG|(null_stdio ? FORK_REARRANGE_STDIO : 0)|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid); if (r < 0) return r; if (r == 0) { diff --git a/src/shutdown/umount.c b/src/shutdown/umount.c index 61bd9d2601..bae4d9d023 100644 --- a/src/shutdown/umount.c +++ b/src/shutdown/umount.c @@ -618,7 +618,10 @@ static int remount_with_timeout(MountPoint *m, bool last_try) { /* Due to the possibility of a remount operation hanging, we fork a child process and set a * timeout. If the timeout lapses, the assumption is that the particular remount failed. */ - r = safe_fork_full("(sd-remount)", pfd, ELEMENTSOF(pfd), FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &pid); + r = safe_fork_full("(sd-remount)", + NULL, + pfd, ELEMENTSOF(pfd), + FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &pid); if (r < 0) return r; if (r == 0) { @@ -671,7 +674,10 @@ static int umount_with_timeout(MountPoint *m, bool last_try) { /* Due to the possibility of a umount operation hanging, we fork a child process and set a * timeout. If the timeout lapses, the assumption is that the particular umount failed. */ - r = safe_fork_full("(sd-umount)", pfd, ELEMENTSOF(pfd), FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &pid); + r = safe_fork_full("(sd-umount)", + NULL, + pfd, ELEMENTSOF(pfd), + FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &pid); if (r < 0) return r; if (r == 0) { diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c index 9c24ca8204..9a0c15dffe 100644 --- a/src/test/test-process-util.c +++ b/src/test/test-process-util.c @@ -589,7 +589,7 @@ TEST(safe_fork) { BLOCK_SIGNALS(SIGCHLD); - r = safe_fork("(test-child)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_NULL_STDIO|FORK_REOPEN_LOG, &pid); + r = safe_fork("(test-child)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_REOPEN_LOG, &pid); assert_se(r >= 0); if (r == 0) { |