/* 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;
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);
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,