#include "fd-util.h"
#include "log.h"
#include "namespace-util.h"
+#include "pidref.h"
#include "process-util.h"
#include "runtime-scope.h"
#include "strv.h"
return log_oom();
}
- pid_t child;
+ _cleanup_(pidref_done) PidRef child = PIDREF_NULL;
r = namespace_fork(
"(unit-shell-ns)",
"(unit-shell)",
- /* except_fds= */ NULL,
- /* n_except_fds= */ 0,
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
pidns_fd,
mntns_fd,
_exit(EXIT_FAILURE);
}
- return wait_for_terminate_and_check(
+ return pidref_wait_for_terminate_and_check(
"(unit-shell)",
- child,
+ &child,
WAIT_LOG_ABNORMAL|WAIT_LOG_NON_ZERO_EXIT_STATUS);
}
return r;
}
-int namespace_fork(
+int namespace_fork_full(
const char *outer_name,
const char *inner_name,
int except_fds[],
int netns_fd,
int userns_fd,
int root_fd,
- pid_t *ret_pid) {
+ PidRef *ret) {
int r;
* /proc/self/fd works correctly. */
assert(!FLAGS_SET(flags, FORK_ALLOW_DLOPEN)); /* never allow loading shared library from another ns */
- r = 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), ret_pid);
+ 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),
+ ret);
if (r < 0)
return r;
if (r == 0) {
- pid_t pid;
+ _cleanup_(pidref_done) PidRef pidref_inner = PIDREF_NULL;
/* Child */
}
/* 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,
- NULL,
- except_fds, n_except_fds,
- flags & ~(FORK_WAIT|FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REARRANGE_STDIO), &pid);
+ r = pidref_safe_fork_full(
+ inner_name,
+ NULL,
+ except_fds, n_except_fds,
+ flags & ~(FORK_WAIT|FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REARRANGE_STDIO),
+ &pidref_inner);
if (r < 0)
_exit(EXIT_FAILURE);
if (r == 0) {
/* Child */
- if (ret_pid)
- *ret_pid = pid;
+ if (ret)
+ *ret = TAKE_PIDREF(pidref_inner);
return 0;
}
- r = wait_for_terminate_and_check(inner_name, pid, FLAGS_SET(flags, FORK_LOG) ? WAIT_LOG : 0);
+ r = pidref_wait_for_terminate_and_check(
+ inner_name,
+ &pidref_inner,
+ FLAGS_SET(flags, FORK_LOG) ? WAIT_LOG : 0);
if (r < 0)
_exit(EXIT_FAILURE);
return safe_fork_full(name, NULL, NULL, 0, flags, ret_pid);
}
-int namespace_fork(
+int namespace_fork_full(
const char *outer_name,
const char *inner_name,
int except_fds[],
int netns_fd,
int userns_fd,
int root_fd,
- pid_t *ret_pid);
+ PidRef *ret);
+
+static inline int namespace_fork(
+ const char *outer_name,
+ const char *inner_name,
+ ForkFlags flags,
+ int pidns_fd,
+ int mntns_fd,
+ int netns_fd,
+ int userns_fd,
+ int root_fd,
+ PidRef *ret) {
+
+ return namespace_fork_full(outer_name, inner_name, NULL, 0, flags,
+ pidns_fd, mntns_fd, netns_fd, userns_fd, root_fd,
+ ret);
+}
int set_oom_score_adjust(int value);
int get_oom_score_adjust(int *ret);
r = namespace_fork(
"(sd-openptns)",
"(sd-openpt)",
- /* except_fds= */ NULL,
- /* n_except_fds= */ 0,
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_WAIT,
pidnsfd,
mntnsfd,
/* netns_fd= */ -EBADF,
usernsfd,
rootfd,
- /* ret_pid= */ NULL);
+ /* ret= */ NULL);
if (r < 0)
return r;
if (r == 0) {
if (r == 0) {
/* Child (host namespace) */
_cleanup_close_pair_ int pair[2] = EBADF_PAIR;
- _cleanup_(sigkill_waitp) pid_t grandchild_pid = 0;
+ _cleanup_(pidref_done_sigkill_wait) PidRef grandchild = PIDREF_NULL;
(void) mkdir_p_label(overlay_prefix, 0555);
_exit(EXIT_FAILURE);
}
- r = safe_fork("(sd-ns-refresh-exts-grandchild)",
- FORK_LOG|FORK_DEATHSIG_SIGKILL,
- &grandchild_pid);
+ r = pidref_safe_fork("(sd-ns-refresh-exts-grandchild)", FORK_LOG|FORK_DEATHSIG_SIGKILL, &grandchild);
if (r < 0)
_exit(EXIT_FAILURE);
if (r == 0) {
_exit(EXIT_FAILURE);
}
- r = wait_for_terminate_and_check("(sd-ns-refresh-exts-grandchild)", TAKE_PID(grandchild_pid), 0);
+ r = pidref_wait_for_terminate_and_check("(sd-ns-refresh-exts-grandchild)", &grandchild, 0);
if (r < 0) {
log_debug_errno(r, "Failed to wait for target namespace process to finish: %m");
_exit(EXIT_FAILURE);
}
+
+ pidref_done(&grandchild);
+
if (r != EXIT_SUCCESS) {
log_debug("Target namespace fork did not succeed");
_exit(EXIT_FAILURE);
}
int coredump_send_to_container(CoredumpContext *context) {
- _cleanup_close_ int pidnsfd = -EBADF, mntnsfd = -EBADF, netnsfd = -EBADF, usernsfd = -EBADF, rootfd = -EBADF;
- _cleanup_close_pair_ int pair[2] = EBADF_PAIR;
- pid_t child;
- struct ucred ucred = {
- .pid = context->pidref.pid,
- .uid = context->uid,
- .gid = context->gid,
- };
int r;
assert(context);
if (r <= 0)
return r;
+ _cleanup_close_ int pidnsfd = -EBADF, mntnsfd = -EBADF, netnsfd = -EBADF, usernsfd = -EBADF, rootfd = -EBADF;
+ _cleanup_(pidref_done) PidRef child = PIDREF_NULL;
+ _cleanup_close_pair_ int pair[2] = EBADF_PAIR;
+ struct ucred ucred = {
+ .pid = context->pidref.pid,
+ .uid = context->uid,
+ .gid = context->gid,
+ };
+
r = RET_NERRNO(socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, pair));
if (r < 0)
return log_debug_errno(r, "Failed to create socket pair: %m");
if (r < 0)
return log_debug_errno(r, "Failed to open namespaces of PID " PID_FMT ": %m", leader_pid.pid);
- r = namespace_fork("(sd-coredumpns)", "(sd-coredump)", NULL, 0,
+ r = namespace_fork("(sd-coredumpns)", "(sd-coredump)",
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM,
pidnsfd, mntnsfd, netnsfd, usernsfd, rootfd, &child);
if (r < 0)
if (r < 0)
return log_debug_errno(r, "Failed to send metadata to container: %m");
- r = wait_for_terminate_and_check("(sd-coredumpns)", child, 0);
+ r = pidref_wait_for_terminate_and_check("(sd-coredumpns)", &child, 0);
if (r < 0)
return log_debug_errno(r, "Failed to wait for child to terminate: %m");
if (r != EXIT_SUCCESS)
r = namespace_fork("(sd-mount-tree-ns)",
"(sd-mount-tree)",
- /* except_fds= */ NULL,
- /* n_except_fds= */ 0,
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_LOG|FORK_WAIT,
/* pidns_fd= */ -EBADF,
mntns_fd,
/* netns_fd= */ -EBADF,
/* userns_fd= */ -EBADF,
root_fd,
- NULL);
+ /* ret= */ NULL);
if (r < 0)
return r;
if (r == 0) {
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include <fcntl.h>
#include <unistd.h>
#include "bus-container.h"
#include "format-util.h"
#include "log.h"
#include "namespace-util.h"
+#include "pidref.h"
#include "process-util.h"
#include "string-util.h"
int bus_container_connect_socket(sd_bus *b) {
- _cleanup_close_pair_ int pair[2] = EBADF_PAIR;
_cleanup_close_ int pidnsfd = -EBADF, mntnsfd = -EBADF, usernsfd = -EBADF, rootfd = -EBADF;
+ _cleanup_(pidref_done) PidRef child = PIDREF_NULL;
+ _cleanup_close_pair_ int pair[2] = EBADF_PAIR;
int r, error_buf = 0;
- pid_t child;
ssize_t n;
assert(b);
if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, pair) < 0)
return log_debug_errno(errno, "Failed to create a socket pair: %m");
- r = namespace_fork("(sd-buscntrns)", "(sd-buscntr)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
+ r = namespace_fork("(sd-buscntrns)", "(sd-buscntr)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
pidnsfd, mntnsfd, -1, usernsfd, rootfd, &child);
if (r < 0)
return log_debug_errno(r, "Failed to create namespace for (sd-buscntr): %m");
pair[1] = safe_close(pair[1]);
- r = wait_for_terminate_and_check("(sd-buscntrns)", child, 0);
+ r = pidref_wait_for_terminate_and_check("(sd-buscntrns)", &child, 0);
if (r < 0)
return r;
bool nonzero_exit_status = r != EXIT_SUCCESS;
#include "id128-util.h"
#include "io-util.h"
#include "namespace-util.h"
+#include "pidref.h"
#include "process-util.h"
#include "sha256.h"
#include "siphash24.h"
int id128_get_boot_for_machine(const char *machine, sd_id128_t *ret) {
_cleanup_close_ int pidnsfd = -EBADF, mntnsfd = -EBADF, rootfd = -EBADF;
+ _cleanup_(pidref_done) PidRef child = PIDREF_NULL;
_cleanup_close_pair_ int pair[2] = EBADF_PAIR;
- pid_t pid, child;
+ pid_t pid;
sd_id128_t id;
ssize_t k;
int r;
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
return -errno;
- r = namespace_fork("(sd-bootidns)", "(sd-bootid)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
+ r = namespace_fork("(sd-bootidns)", "(sd-bootid)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
pidnsfd, mntnsfd, -1, -1, rootfd, &child);
if (r < 0)
return r;
pair[1] = safe_close(pair[1]);
- r = wait_for_terminate_and_check("(sd-bootidns)", child, 0);
+ r = pidref_wait_for_terminate_and_check("(sd-bootidns)", &child, 0);
if (r < 0)
return r;
if (r != EXIT_SUCCESS)
Operation **ret) {
_cleanup_close_ int host_fd = -EBADF, target_mntns_fd = -EBADF, source_mntns_fd = -EBADF;
+ _cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL;
_cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR;
_cleanup_free_ char *host_basename = NULL, *container_basename = NULL;
- _cleanup_(sigkill_waitp) pid_t child = 0;
uid_t uid_shift;
int r;
r = namespace_fork("(sd-copyns)",
"(sd-copy)",
- /* except_fds= */ NULL,
- /* n_except_fds= */ 0,
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
/* pidns_fd= */ -EBADF,
target_mntns_fd,
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
+ // TODO: port to PidRef and donate child rather than destroying it
Operation *operation;
- r = operation_new(manager, machine, child, errno_pipe_fd[0], &operation);
+ r = operation_new(manager, machine, child.pid, errno_pipe_fd[0], &operation);
if (r < 0)
return r;
TAKE_FD(errno_pipe_fd[0]);
- TAKE_PID(child);
+ pidref_done(&child);
*ret = operation;
return 0;
case MACHINE_CONTAINER: {
_cleanup_close_ int mntns_fd = -EBADF, root_fd = -EBADF;
+ _cleanup_(pidref_done) PidRef child = PIDREF_NULL;
_cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR, fd_pass_socket[2] = EBADF_PAIR;
- pid_t child;
r = pidref_namespace_open(&machine->leader,
/* ret_pidns_fd= */ NULL,
r = namespace_fork(
"(sd-openrootns)",
"(sd-openroot)",
- /* except_fds= */ NULL,
- /* n_except_fds= */ 0,
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
/* pidns_fd= */ -EBADF,
mntns_fd,
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
fd_pass_socket[1] = safe_close(fd_pass_socket[1]);
- r = wait_for_terminate_and_check("(sd-openrootns)", child, /* flags= */ 0);
+ r = pidref_wait_for_terminate_and_check("(sd-openrootns)", &child, /* flags= */ 0);
if (r < 0)
return log_debug_errno(r, "Failed to wait for child: %m");
}
case MACHINE_CONTAINER: {
+ _cleanup_(pidref_done) PidRef child = PIDREF_NULL;
_cleanup_close_pair_ int pair[2] = EBADF_PAIR;
_cleanup_close_ int netns_fd = -EBADF;
- pid_t child;
int r;
r = pidref_in_same_namespace(/* pid1= */ NULL, &machine->leader, NAMESPACE_NET);
r = namespace_fork("(sd-addrns)",
"(sd-addr)",
- /* except_fds= */ NULL,
- /* n_except_fds= */ 0,
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
/* pidns_fd= */ -EBADF,
/* mntns_fd= */ -EBADF,
}
}
- pair[1] = safe_close(pair[1]);
-
_exit(EXIT_SUCCESS);
}
return log_debug_errno(r, "Failed to add local address: %m");
}
- r = wait_for_terminate_and_check("(sd-addrns)", child, /* flags= */ 0);
+ r = pidref_wait_for_terminate_and_check("(sd-addrns)", &child, /* flags= */ 0);
if (r < 0)
return log_debug_errno(r, "Failed to wait for child: %m");
if (r != EXIT_SUCCESS)
case MACHINE_CONTAINER: {
_cleanup_close_ int mntns_fd = -EBADF, root_fd = -EBADF, pidns_fd = -EBADF;
+ _cleanup_(pidref_done) PidRef child = PIDREF_NULL;
_cleanup_close_pair_ int pair[2] = EBADF_PAIR;
_cleanup_fclose_ FILE *f = NULL;
- pid_t child;
r = pidref_namespace_open(&machine->leader,
&pidns_fd,
r = namespace_fork("(sd-osrelns)",
"(sd-osrel)",
- /* except_fds= */ NULL,
- /* n_except_fds= */ 0,
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
pidns_fd,
mntns_fd,
if (r < 0)
return log_debug_errno(r, "Failed to load OS release information: %m");
- r = wait_for_terminate_and_check("(sd-osrelns)", child, /* flags= */ 0);
+ r = pidref_wait_for_terminate_and_check("(sd-osrelns)", &child, /* flags= */ 0);
if (r < 0)
return log_debug_errno(r, "Failed to wait for child: %m");
if (r == EXIT_NOT_FOUND)
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include <sched.h>
#include <stdlib.h>
#include <sys/mount.h>
#include <sys/socket.h>
bool mount_slave_created = false, mount_slave_mounted = false,
mount_tmp_created = false, mount_tmp_mounted = false,
mount_outside_created = false, mount_outside_mounted = false;
- pid_t child;
+ _cleanup_(pidref_done) PidRef child = PIDREF_NULL;
int r;
assert(chased_src_path);
r = namespace_fork(
"(sd-bindmnt)",
"(sd-bindmnt-inner)",
- /* except_fds= */ NULL,
- /* n_except_fds= */ 0,
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM,
pidns_fd,
mntns_fd,
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
- r = wait_for_terminate_and_check("(sd-bindmnt)", child, 0);
+ r = pidref_wait_for_terminate_and_check("(sd-bindmnt)", &child, 0);
if (r < 0) {
log_debug_errno(r, "Failed to wait for child: %m");
goto finish;
_cleanup_(dissected_image_unrefp) DissectedImage *img = NULL;
_cleanup_close_ int new_mount_fd = -EBADF;
_cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR;
- pid_t child;
+ _cleanup_(pidref_done) PidRef child = PIDREF_NULL;
if (flags & MOUNT_IN_NAMESPACE_IS_IMAGE) {
r = verity_dissect_and_mount(
r = namespace_fork("(sd-bindmnt)",
"(sd-bindmnt-inner)",
- /* except_fds= */ NULL,
- /* n_except_fds= */ 0,
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM,
pidns_fd,
mntns_fd,
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
- r = wait_for_terminate_and_check("(sd-bindmnt)", child, 0);
+ r = pidref_wait_for_terminate_and_check("(sd-bindmnt)", &child, 0);
if (r < 0)
return log_debug_errno(r, "Failed to wait for child: %m");
if (r != EXIT_SUCCESS) {