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.
This commit is contained in:
Mike Yuan
2025-12-20 14:14:24 +01:00
parent 8c007f68ff
commit ed0f6758c8
+17 -5
View File
@@ -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,