From: Mike Yuan Date: Sun, 14 Dec 2025 15:02:17 +0000 (+0100) Subject: process-util: revamp flags handling in namespace_fork() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ed0f6758c82f4380baf31612290a395bb7df87a6;p=thirdparty%2Fsystemd.git process-util: revamp flags handling in namespace_fork() * Specifying all 3 of FORK_DEATHSIG_SIG{KILL,TERM,INT} for the middle man makes zero sense. Use SIGKILL only. * Make sure operations on except_fds work sensibly - close/pack/ de-ocloexecify fds only in the second level, so that the namespace fds remain usable across first safe_fork(). * Fire FORK_NEW_*NS after attaching to the desired namespaces, not already in the outer process. * Insist on PDEATHSIG being enabled to ensure propagation of killing. * Suppress more redundant flags. --- diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 700fba5cbae..0a87c5ec770 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -1901,14 +1901,21 @@ int namespace_fork_full( /* This is much like safe_fork(), but forks twice, and joins the specified namespaces in the middle * process. This ensures that we are fully a member of the destination namespace, with pidns an all, so that - * /proc/self/fd works correctly. */ + * /proc/self/fd works correctly. + * + * TODO: once we can rely on PIDFD_INFO_EXIT, do not keep the middle process around and instead + * return the pidfd of the inner process for direct tracking. */ + + /* Insist on PDEATHSIG being enabled, as the pid returned is the one of the middle man, and otherwise + * killing of it won't be propagated to the inner child. */ + assert((flags & (FORK_DEATHSIG_SIGKILL|FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGINT)) != 0); + assert((flags & (FORK_DETACH|FORK_FREEZE)) == 0); assert(!FLAGS_SET(flags, FORK_ALLOW_DLOPEN)); /* never allow loading shared library from another ns */ r = pidref_safe_fork_full( outer_name, - NULL, - except_fds, n_except_fds, - (flags|FORK_DEATHSIG_SIGINT|FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGKILL) & ~(FORK_REOPEN_LOG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE), + /* stdio_fds = */ NULL, /* except_fds = */ NULL, /* n_except_fds = */ 0, + (flags|FORK_DEATHSIG_SIGKILL) & ~(FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGINT|FORK_REOPEN_LOG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_NEW_USERNS|FORK_NEW_NETNS|FORK_NEW_PIDNS|FORK_CLOSE_ALL_FDS|FORK_PACK_FDS|FORK_CLOEXEC_OFF|FORK_RLIMIT_NOFILE_SAFE), ret); if (r < 0) return r; @@ -1928,7 +1935,7 @@ int namespace_fork_full( inner_name, NULL, except_fds, n_except_fds, - flags & ~(FORK_WAIT|FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REARRANGE_STDIO), + flags & ~(FORK_WAIT|FORK_RESET_SIGNALS|FORK_REARRANGE_STDIO|FORK_FLUSH_STDIO|FORK_STDOUT_TO_STDERR), &pidref_inner); if (r < 0) _exit(EXIT_FAILURE); @@ -1939,6 +1946,11 @@ int namespace_fork_full( return 0; } + log_close(); + log_set_open_when_needed(true); + + (void) close_all_fds(&pidref_inner.fd, 1); + r = pidref_wait_for_terminate_and_check( inner_name, &pidref_inner,