tree-wide: Use pidref_wait_for_terminate_and_check()

Let's use the pidref variants for waiting and
checking a process everywhere and get rid of the
non pidref variants.
This commit is contained in:
Daan De Meyer
2025-12-20 15:50:47 +01:00
parent e74b571004
commit fbd276cb86
56 changed files with 620 additions and 654 deletions
+5 -5
View File
@@ -15,6 +15,7 @@
#include "lock-util.h"
#include "log.h"
#include "path-util.h"
#include "pidref.h"
#include "process-util.h"
#include "string-util.h"
#include "time-util.h"
@@ -199,7 +200,6 @@ int lock_generic(int fd, LockType type, int operation) {
}
int lock_generic_with_timeout(int fd, LockType type, int operation, usec_t timeout) {
_cleanup_(sigkill_waitp) pid_t pid = 0;
int r;
assert(fd >= 0);
@@ -223,8 +223,8 @@ int lock_generic_with_timeout(int fd, LockType type, int operation, usec_t timeo
return r;
/* If that didn't work, try with a child */
r = safe_fork("(sd-flock)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL, &pid);
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
r = pidref_safe_fork("(sd-flock)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL, &pidref);
if (r < 0)
return log_error_errno(r, "Failed to flock block device in child process: %m");
if (r == 0) {
@@ -256,11 +256,11 @@ int lock_generic_with_timeout(int fd, LockType type, int operation, usec_t timeo
}
siginfo_t status;
r = wait_for_terminate(pid, &status);
r = pidref_wait_for_terminate(&pidref, &status);
if (r < 0)
return r;
TAKE_PID(pid);
pidref_done(&pidref);
switch (status.si_code) {
+10 -10
View File
@@ -601,25 +601,25 @@ int userns_acquire_self_root(void) {
return userns_acquire(uid_map, gid_map, /* setgroups_deny= */ true);
}
int userns_enter_and_pin(int userns_fd, pid_t *ret_pid) {
int userns_enter_and_pin(int userns_fd, PidRef *ret) {
_cleanup_close_pair_ int pfd[2] = EBADF_PAIR;
_cleanup_(sigkill_waitp) pid_t pid = 0;
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
ssize_t n;
char x;
int r;
assert(userns_fd >= 0);
assert(ret_pid);
assert(ret);
if (pipe2(pfd, O_CLOEXEC) < 0)
return -errno;
r = safe_fork_full(
r = pidref_safe_fork_full(
"(sd-pinuserns)",
/* stdio_fds= */ NULL,
(int[]) { pfd[1], userns_fd }, 2,
FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL,
&pid);
&pidref);
if (r < 0)
return r;
if (r == 0) {
@@ -652,7 +652,7 @@ int userns_enter_and_pin(int userns_fd, pid_t *ret_pid) {
assert(n == 1);
assert(x == 'x');
*ret_pid = TAKE_PID(pid);
*ret = TAKE_PIDREF(pidref);
return 0;
}
@@ -661,22 +661,22 @@ bool userns_supported(void) {
}
int userns_get_base_uid(int userns_fd, uid_t *ret_uid, gid_t *ret_gid) {
_cleanup_(sigkill_waitp) pid_t pid = 0;
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
int r;
assert(userns_fd >= 0);
r = userns_enter_and_pin(userns_fd, &pid);
r = userns_enter_and_pin(userns_fd, &pidref);
if (r < 0)
return r;
uid_t uid;
r = uid_map_search_root(pid, UID_RANGE_USERNS_OUTSIDE, &uid);
r = uid_map_search_root(pidref.pid, UID_RANGE_USERNS_OUTSIDE, &uid);
if (r < 0)
return r;
gid_t gid;
r = uid_map_search_root(pid, GID_RANGE_USERNS_OUTSIDE, &gid);
r = uid_map_search_root(pidref.pid, GID_RANGE_USERNS_OUTSIDE, &gid);
if (r < 0)
return r;
+1 -1
View File
@@ -82,7 +82,7 @@ int parse_userns_uid_range(const char *s, uid_t *ret_uid_shift, uid_t *ret_uid_r
int userns_acquire_empty(void);
int userns_acquire(const char *uid_map, const char *gid_map, bool setgroups_deny);
int userns_acquire_self_root(void);
int userns_enter_and_pin(int userns_fd, pid_t *ret_pid);
int userns_enter_and_pin(int userns_fd, PidRef *ret);
bool userns_supported(void);
int userns_get_base_uid(int userns_fd, uid_t *ret_uid, gid_t *ret_gid);
+9
View File
@@ -101,6 +101,15 @@ static inline int pidref_wait_for_terminate(PidRef *pidref, siginfo_t *ret) {
return pidref_wait_for_terminate_full(pidref, USEC_INFINITY, ret);
}
static inline void pidref_done_sigterm_wait(PidRef *pidref) {
if (!pidref_is_set(pidref))
return;
(void) pidref_kill(pidref, SIGTERM);
(void) pidref_wait_for_terminate(pidref, NULL);
pidref_done(pidref);
}
static inline void pidref_done_sigkill_wait(PidRef *pidref) {
if (!pidref_is_set(pidref))
return;
+4 -52
View File
@@ -845,13 +845,9 @@ int get_process_umask(pid_t pid, mode_t *ret) {
return parse_mode(m, ret);
}
int wait_for_terminate(pid_t pid, siginfo_t *ret) {
return pidref_wait_for_terminate(&PIDREF_MAKE_FROM_PID(pid), ret);
}
/*
* Return values:
* < 0 : wait_for_terminate() failed to get the state of the
* < 0 : pidref_wait_for_terminate() failed to get the state of the
* process, the process was terminated by a signal, or
* failed for an unknown reason.
* >=0 : The process terminated normally, and its exit code is
@@ -908,52 +904,6 @@ int pidref_wait_for_terminate_and_check(const char *name, PidRef *pidref, WaitFl
return -EPROTO;
}
int wait_for_terminate_and_check(const char *name, pid_t pid, WaitFlags flags) {
return pidref_wait_for_terminate_and_check(name, &PIDREF_MAKE_FROM_PID(pid), flags);
}
void sigkill_wait(pid_t pid) {
assert(pid > 1);
(void) kill(pid, SIGKILL);
(void) wait_for_terminate(pid, NULL);
}
void sigkill_waitp(pid_t *pid) {
PROTECT_ERRNO;
if (!pid)
return;
if (*pid <= 1)
return;
sigkill_wait(*pid);
}
void sigterm_wait(pid_t pid) {
assert(pid > 1);
(void) kill_and_sigcont(pid, SIGTERM);
(void) wait_for_terminate(pid, NULL);
}
void sigkill_nowait(pid_t pid) {
assert(pid > 1);
(void) kill(pid, SIGKILL);
}
void sigkill_nowaitp(pid_t *pid) {
PROTECT_ERRNO;
if (!pid)
return;
if (*pid <= 1)
return;
sigkill_nowait(*pid);
}
int kill_and_sigcont(pid_t pid, int sig) {
int r;
@@ -1280,7 +1230,9 @@ void valgrind_summary_hack(void) {
exit(EXIT_SUCCESS);
else {
log_info("Spawned valgrind helper as PID "PID_FMT".", pid);
(void) wait_for_terminate(pid, NULL);
_cleanup_(pidref_done) PidRef pidref = PIDREF_MAKE_FROM_PID(pid);
(void) pidref_set_pid(&pidref, pid);
(void) pidref_wait_for_terminate(&pidref, NULL);
}
}
#endif
-9
View File
@@ -60,8 +60,6 @@ static inline bool SIGINFO_CODE_IS_DEAD(int code) {
return IN_SET(code, CLD_EXITED, CLD_KILLED, CLD_DUMPED);
}
int wait_for_terminate(pid_t pid, siginfo_t *ret);
typedef enum WaitFlags {
WAIT_LOG_ABNORMAL = 1 << 0,
WAIT_LOG_NON_ZERO_EXIT_STATUS = 1 << 1,
@@ -71,13 +69,6 @@ typedef enum WaitFlags {
} WaitFlags;
int pidref_wait_for_terminate_and_check(const char *name, PidRef *pidref, WaitFlags flags);
int wait_for_terminate_and_check(const char *name, pid_t pid, WaitFlags flags);
void sigkill_wait(pid_t pid);
void sigkill_waitp(pid_t *pid);
void sigterm_wait(pid_t pid);
void sigkill_nowait(pid_t pid);
void sigkill_nowaitp(pid_t *pid);
int kill_and_sigcont(pid_t pid, int sig);
+4 -3
View File
@@ -8,6 +8,7 @@
#include "format-util.h"
#include "namespace-util.h"
#include "path-util.h"
#include "pidref.h"
#include "process-util.h"
#include "sort-util.h"
#include "stat-util.h"
@@ -286,7 +287,7 @@ int uid_range_load_userns(const char *path, UIDRangeUsernsMode mode, UIDRange **
}
int uid_range_load_userns_by_fd(int userns_fd, UIDRangeUsernsMode mode, UIDRange **ret) {
_cleanup_(sigkill_waitp) pid_t pid = 0;
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
int r;
assert(userns_fd >= 0);
@@ -294,12 +295,12 @@ int uid_range_load_userns_by_fd(int userns_fd, UIDRangeUsernsMode mode, UIDRange
assert(mode < _UID_RANGE_USERNS_MODE_MAX);
assert(ret);
r = userns_enter_and_pin(userns_fd, &pid);
r = userns_enter_and_pin(userns_fd, &pidref);
if (r < 0)
return r;
const char *p = procfs_file_alloca(
pid,
pidref.pid,
IN_SET(mode, UID_RANGE_USERNS_INSIDE, UID_RANGE_USERNS_OUTSIDE) ? "uid_map" : "gid_map");
return uid_range_load_userns(p, mode, ret);
+8 -2
View File
@@ -12,6 +12,7 @@
#include "format-util.h"
#include "log.h"
#include "main.h"
#include "pidref.h"
#include "process-util.h"
#include "raw-clone.h"
#include "rlimit-util.h"
@@ -127,8 +128,11 @@ _noreturn_ static void crash(int sig, siginfo_t *siginfo, void *context) {
LOG_MESSAGE_ID(SD_MESSAGE_CRASH_PROCESS_SIGNAL_STR));
}
_cleanup_(pidref_done) PidRef pidref = PIDREF_MAKE_FROM_PID(pid);
(void) pidref_set_pid(&pidref, pid);
/* Order things nicely. */
r = wait_for_terminate(pid, &status);
r = pidref_wait_for_terminate(&pidref, &status);
if (r < 0)
log_struct_errno(LOG_EMERG, r,
LOG_MESSAGE("Caught <%s>, waitpid() failed: %m", signal_to_string(sig)),
@@ -181,7 +185,9 @@ _noreturn_ static void crash(int sig, siginfo_t *siginfo, void *context) {
_exit(EXIT_EXCEPTION);
} else {
log_info("Spawned crash shell as PID "PID_FMT".", pid);
(void) wait_for_terminate(pid, NULL);
_cleanup_(pidref_done) PidRef pidref = PIDREF_MAKE_FROM_PID(pid);
(void) pidref_set_pid(&pidref, pid);
(void) pidref_wait_for_terminate(&pidref, NULL);
}
}
+11 -7
View File
@@ -2406,7 +2406,7 @@ static int setup_private_users(PrivateUsers private_users, uid_t ouid, gid_t ogi
_cleanup_free_ char *uid_map = NULL, *gid_map = NULL;
_cleanup_close_pair_ int errno_pipe[2] = EBADF_PAIR;
_cleanup_close_ int unshare_ready_fd = -EBADF;
_cleanup_(sigkill_waitp) pid_t pid = 0;
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
uint64_t c = 1;
ssize_t n;
int r;
@@ -2503,7 +2503,7 @@ static int setup_private_users(PrivateUsers private_users, uid_t ouid, gid_t ogi
if (pipe2(errno_pipe, O_CLOEXEC) < 0)
return -errno;
r = safe_fork("(sd-userns)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL, &pid);
r = pidref_safe_fork("(sd-userns)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL, &pidref);
if (r < 0)
return r;
if (r == 0) {
@@ -2535,9 +2535,10 @@ static int setup_private_users(PrivateUsers private_users, uid_t ouid, gid_t ogi
if (n != 0) /* on success we should have read 0 bytes */
return -EIO;
r = wait_for_terminate_and_check("(sd-userns)", TAKE_PID(pid), 0);
r = pidref_wait_for_terminate_and_check("(sd-userns)", &pidref, 0);
if (r < 0)
return r;
pidref_done(&pidref);
if (r != EXIT_SUCCESS) /* If something strange happened with the child, let's consider this fatal, too */
return -EIO;
@@ -2546,7 +2547,7 @@ static int setup_private_users(PrivateUsers private_users, uid_t ouid, gid_t ogi
static int can_mount_proc(void) {
_cleanup_close_pair_ int errno_pipe[2] = EBADF_PAIR;
_cleanup_(sigkill_waitp) pid_t pid = 0;
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
ssize_t n;
int r;
@@ -2561,8 +2562,10 @@ static int can_mount_proc(void) {
/* Fork a child process into its own mount and PID namespace. Note safe_fork() already remounts / as SLAVE
* with FORK_MOUNTNS_SLAVE. */
r = safe_fork("(sd-proc-check)",
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_NEW_PIDNS, &pid);
r = pidref_safe_fork(
"(sd-proc-check)",
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_NEW_PIDNS,
&pidref);
if (r < 0)
return log_debug_errno(r, "Failed to fork child process (sd-proc-check): %m");
if (r == 0) {
@@ -2597,9 +2600,10 @@ static int can_mount_proc(void) {
if (n != 0) /* on success we should have read 0 bytes */
return -EIO;
r = wait_for_terminate_and_check("(sd-proc-check)", TAKE_PID(pid), /* flags= */ 0);
r = pidref_wait_for_terminate_and_check("(sd-proc-check)", &pidref, /* flags= */ 0);
if (r < 0)
return log_debug_errno(r, "Failed to wait for (sd-proc-check) child process to terminate: %m");
pidref_done(&pidref);
if (r != EXIT_SUCCESS) /* If something strange happened with the child, let's consider this fatal, too */
return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Child process (sd-proc-check) exited with unexpected exit status '%d'.", r);
+7 -3
View File
@@ -42,6 +42,7 @@
#include "parse-argument.h"
#include "parse-util.h"
#include "path-util.h"
#include "pidref.h"
#include "pretty-print.h"
#include "process-util.h"
#include "signal-util.h"
@@ -1177,7 +1178,6 @@ static int run_debug(int argc, char **argv, void *userdata) {
bool unlink_path = false;
const char *data, *fork_name;
size_t len;
pid_t pid;
int r;
if (!arg_debugger) {
@@ -1271,7 +1271,11 @@ static int run_debug(int argc, char **argv, void *userdata) {
fork_name = strjoina("(", debugger_call[0], ")");
r = safe_fork(fork_name, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG|FORK_FLUSH_STDIO, &pid);
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = pidref_safe_fork(
fork_name,
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG|FORK_FLUSH_STDIO,
&pidref);
if (r < 0)
goto finish;
if (r == 0) {
@@ -1281,7 +1285,7 @@ static int run_debug(int argc, char **argv, void *userdata) {
_exit(EXIT_FAILURE);
}
r = wait_for_terminate_and_check(debugger_call[0], pid, WAIT_LOG_ABNORMAL);
r = pidref_wait_for_terminate_and_check(debugger_call[0], &pidref, WAIT_LOG_ABNORMAL);
finish:
(void) default_signals(SIGINT, SIGTERM);
+7 -3
View File
@@ -19,6 +19,7 @@
#include "pager.h"
#include "parse-argument.h"
#include "path-util.h"
#include "pidref.h"
#include "pretty-print.h"
#include "process-util.h"
#include "stat-util.h"
@@ -140,7 +141,6 @@ static int notify_override_unchanged(const char *f) {
static int found_override(const char *top, const char *bottom) {
_cleanup_free_ char *dest = NULL;
pid_t pid;
int r;
assert(top);
@@ -165,7 +165,11 @@ static int found_override(const char *top, const char *bottom) {
fflush(stdout);
r = safe_fork("(diff)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = pidref_safe_fork(
"(diff)",
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG,
&pidref);
if (r < 0)
return r;
if (r == 0) {
@@ -175,7 +179,7 @@ static int found_override(const char *top, const char *bottom) {
_exit(EXIT_FAILURE);
}
(void) wait_for_terminate_and_check("diff", pid, WAIT_LOG_ABNORMAL);
(void) pidref_wait_for_terminate_and_check("diff", &pidref, WAIT_LOG_ABNORMAL);
putchar('\n');
return r;
+7 -3
View File
@@ -23,6 +23,7 @@
#include "fsck-util.h"
#include "main-func.h"
#include "path-util.h"
#include "pidref.h"
#include "proc-cmdline.h"
#include "process-util.h"
#include "socket-util.h"
@@ -267,7 +268,6 @@ static int run(int argc, char *argv[]) {
bool root_directory;
struct stat st;
int r, exit_status;
pid_t pid;
log_setup();
@@ -366,7 +366,11 @@ static int run(int argc, char *argv[]) {
pipe(progress_pipe) < 0)
return log_error_errno(errno, "pipe(): %m");
r = safe_fork("(fsck)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, &pid);
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = pidref_safe_fork(
"(fsck)",
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
&pidref);
if (r < 0)
return r;
if (r == 0) {
@@ -424,7 +428,7 @@ static int run(int argc, char *argv[]) {
(void) process_progress(TAKE_FD(progress_pipe[0]), console);
}
exit_status = wait_for_terminate_and_check("fsck", pid, WAIT_LOG_ABNORMAL);
exit_status = pidref_wait_for_terminate_and_check("fsck", &pidref, WAIT_LOG_ABNORMAL);
if (exit_status < 0)
return exit_status;
if ((exit_status & ~FSCK_ERROR_CORRECTED) != FSCK_SUCCESS) {
+7 -3
View File
@@ -46,6 +46,7 @@
#include "password-quality-util.h"
#include "path-util.h"
#include "percent-util.h"
#include "pidref.h"
#include "pkcs11-util.h"
#include "polkit-agent.h"
#include "pretty-print.h"
@@ -2341,7 +2342,6 @@ static int with_home(int argc, char *argv[], void *userdata) {
_cleanup_strv_free_ char **cmdline = NULL;
const char *home;
int r, ret;
pid_t pid;
r = acquire_bus(&bus);
if (r < 0)
@@ -2414,7 +2414,11 @@ static int with_home(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_parse_error(r);
r = safe_fork("(with)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REOPEN_LOG, &pid);
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = pidref_safe_fork(
"(with)",
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REOPEN_LOG,
&pidref);
if (r < 0)
return r;
if (r == 0) {
@@ -2428,7 +2432,7 @@ static int with_home(int argc, char *argv[], void *userdata) {
_exit(255);
}
ret = wait_for_terminate_and_check(cmdline[0], pid, WAIT_LOG_ABNORMAL);
ret = pidref_wait_for_terminate_and_check(cmdline[0], &pidref, WAIT_LOG_ABNORMAL);
/* Close the fd that pings the home now. */
acquired_fd = safe_close(acquired_fd);
+7 -3
View File
@@ -15,6 +15,7 @@
#include "memfd-util.h"
#include "mount-util.h"
#include "path-util.h"
#include "pidref.h"
#include "process-util.h"
#include "stat-util.h"
#include "string-util.h"
@@ -75,14 +76,17 @@ int home_setup_cifs(
STRV_FOREACH(pw, h->password) {
_cleanup_close_ int passwd_fd = -EBADF;
pid_t mount_pid;
int exit_status;
passwd_fd = memfd_new_and_seal_string("cifspw", *pw);
if (passwd_fd < 0)
return log_error_errno(passwd_fd, "Failed to create data FD for password: %m");
r = safe_fork("(mount)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_STDOUT_TO_STDERR, &mount_pid);
_cleanup_(pidref_done) PidRef mount_pidref = PIDREF_NULL;
r = pidref_safe_fork(
"(mount)",
FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_STDOUT_TO_STDERR,
&mount_pidref);
if (r < 0)
return r;
if (r == 0) {
@@ -108,7 +112,7 @@ int home_setup_cifs(
_exit(EXIT_FAILURE);
}
exit_status = wait_for_terminate_and_check("mount", mount_pid, WAIT_LOG_ABNORMAL|WAIT_LOG_NON_ZERO_EXIT_STATUS);
exit_status = pidref_wait_for_terminate_and_check("mount", &mount_pidref, WAIT_LOG_ABNORMAL|WAIT_LOG_NON_ZERO_EXIT_STATUS);
if (exit_status < 0)
return exit_status;
if (exit_status == EXIT_SUCCESS) {
+17 -13
View File
@@ -7,6 +7,7 @@
#include <sys/ioctl.h>
#include <sys/xattr.h>
#include <unistd.h>
#include "pidref.h"
#if HAVE_VALGRIND_MEMCHECK_H
#include <valgrind/memcheck.h>
#endif
@@ -227,7 +228,6 @@ static int block_get_size_by_path(const char *path, uint64_t *ret) {
static int run_fsck(const char *node, const char *fstype) {
int r, exit_status;
pid_t fsck_pid;
assert(node);
assert(fstype);
@@ -240,9 +240,11 @@ static int run_fsck(const char *node, const char *fstype) {
return 0;
}
r = safe_fork("(fsck)",
FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS,
&fsck_pid);
_cleanup_(pidref_done) PidRef fsck_pidref = PIDREF_NULL;
r = pidref_safe_fork(
"(fsck)",
FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS,
&fsck_pidref);
if (r < 0)
return r;
if (r == 0) {
@@ -253,7 +255,7 @@ static int run_fsck(const char *node, const char *fstype) {
_exit(FSCK_OPERATIONAL_ERROR);
}
exit_status = wait_for_terminate_and_check("fsck", fsck_pid, WAIT_LOG_ABNORMAL);
exit_status = pidref_wait_for_terminate_and_check("fsck", &fsck_pidref, WAIT_LOG_ABNORMAL);
if (exit_status < 0)
return exit_status;
if ((exit_status & ~FSCK_ERROR_CORRECTED) != 0) {
@@ -2604,7 +2606,7 @@ static int ext4_offline_resize_fs(
_cleanup_free_ char *size_str = NULL;
bool re_open = false, re_mount = false;
pid_t resize_pid, fsck_pid;
_cleanup_(pidref_done) PidRef resize_pidref = PIDREF_NULL, fsck_pidref = PIDREF_NULL;
int r, exit_status;
assert(setup);
@@ -2627,9 +2629,10 @@ static int ext4_offline_resize_fs(
log_info("Temporary unmounting of file system completed.");
/* resize2fs requires that the file system is force checked first, do so. */
r = safe_fork("(e2fsck)",
FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS,
&fsck_pid);
r = pidref_safe_fork(
"(e2fsck)",
FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS,
&fsck_pidref);
if (r < 0)
return r;
if (r == 0) {
@@ -2640,7 +2643,7 @@ static int ext4_offline_resize_fs(
_exit(EXIT_FAILURE);
}
exit_status = wait_for_terminate_and_check("e2fsck", fsck_pid, WAIT_LOG_ABNORMAL);
exit_status = pidref_wait_for_terminate_and_check("e2fsck", &fsck_pidref, WAIT_LOG_ABNORMAL);
if (exit_status < 0)
return exit_status;
if ((exit_status & ~FSCK_ERROR_CORRECTED) != 0) {
@@ -2659,9 +2662,10 @@ static int ext4_offline_resize_fs(
return log_oom();
/* Resize the thing */
r = safe_fork("(e2resize)",
FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS,
&resize_pid);
r = pidref_safe_fork(
"(e2resize)",
FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS,
&resize_pidref);
if (r < 0)
return r;
if (r == 0) {
+10 -7
View File
@@ -12,6 +12,7 @@
#include "memory-util.h"
#include "os-util.h"
#include "path-util.h"
#include "pidref.h"
#include "process-util.h"
#include "pull-common.h"
#include "pull-job.h"
@@ -404,7 +405,7 @@ static int verify_gpg(
_cleanup_close_pair_ int gpg_pipe[2] = EBADF_PAIR;
_cleanup_(rm_rf_physical_and_freep) char *gpg_home = NULL;
char sig_file_path[] = "/tmp/sigXXXXXX";
_cleanup_(sigkill_waitp) pid_t pid = 0;
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
int r;
assert(iovec_is_valid(payload));
@@ -434,11 +435,12 @@ static int verify_gpg(
goto finish;
}
r = safe_fork_full("(gpg)",
(int[]) { gpg_pipe[0], -EBADF, STDERR_FILENO },
NULL, 0,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
&pid);
r = pidref_safe_fork_full(
"(gpg)",
(int[]) { gpg_pipe[0], -EBADF, STDERR_FILENO },
/* except_fds= */ NULL, /* n_except_fds= */ 0,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
&pidref);
if (r < 0)
return r;
if (r == 0) {
@@ -497,9 +499,10 @@ static int verify_gpg(
gpg_pipe[1] = safe_close(gpg_pipe[1]);
r = wait_for_terminate_and_check("gpg", TAKE_PID(pid), WAIT_LOG_ABNORMAL);
r = pidref_wait_for_terminate_and_check("gpg", &pidref, WAIT_LOG_ABNORMAL);
if (r < 0)
goto finish;
pidref_done(&pidref);
if (r != EXIT_SUCCESS)
r = log_error_errno(SYNTHETIC_ERRNO(EBADMSG),
"DOWNLOAD INVALID: Signature verification failed.");
+2 -1
View File
@@ -8,6 +8,7 @@
#include "bus-match.h"
#include "constants.h"
#include "list.h"
#include "pidref.h"
#include "runtime-scope.h"
#include "socket-util.h"
@@ -271,7 +272,7 @@ typedef struct sd_bus {
unsigned n_memfd_cache;
uint64_t origin_id;
pid_t busexec_pid;
PidRef busexec_pidref;
unsigned iteration_counter;
+7 -5
View File
@@ -1163,7 +1163,7 @@ int bus_socket_exec(sd_bus *b) {
assert(b->input_fd < 0);
assert(b->output_fd < 0);
assert(b->exec_path);
assert(b->busexec_pid == 0);
assert(!pidref_is_set(&b->busexec_pidref));
if (DEBUG_LOGGING) {
_cleanup_free_ char *line = NULL;
@@ -1181,10 +1181,12 @@ int bus_socket_exec(sd_bus *b) {
if (r < 0)
return -errno;
r = safe_fork_full("(sd-busexec)",
(int[]) { s[1], s[1], STDERR_FILENO },
NULL, 0,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REARRANGE_STDIO|FORK_RLIMIT_NOFILE_SAFE, &b->busexec_pid);
r = pidref_safe_fork_full(
"(sd-busexec)",
(int[]) { s[1], s[1], STDERR_FILENO },
NULL, 0,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REARRANGE_STDIO|FORK_RLIMIT_NOFILE_SAFE,
&b->busexec_pidref);
if (r < 0) {
safe_close_pair(s);
return r;
+4 -11
View File
@@ -41,7 +41,6 @@
#include "parse-util.h"
#include "path-util.h"
#include "prioq.h"
#include "process-util.h"
#include "set.h"
#include "string-util.h"
#include "strv.h"
@@ -262,6 +261,7 @@ _public_ int sd_bus_new(sd_bus **ret) {
.creds_mask = SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME,
.accept_fd = true,
.origin_id = origin_id_query(),
.busexec_pidref = PIDREF_NULL,
.n_groups = SIZE_MAX,
.close_on_exit = true,
.ucred = UCRED_INVALID,
@@ -1121,13 +1121,6 @@ static int bus_parse_next_address(sd_bus *b) {
return 1;
}
static void bus_kill_exec(sd_bus *bus) {
if (!pid_is_valid(bus->busexec_pid))
return;
sigterm_wait(TAKE_PID(bus->busexec_pid));
}
static int bus_start_address(sd_bus *b) {
int r;
@@ -1136,7 +1129,7 @@ static int bus_start_address(sd_bus *b) {
for (;;) {
bus_close_fds(b);
bus_kill_exec(b);
pidref_done_sigterm_wait(&b->busexec_pidref);
/* If you provide multiple different bus-addresses, we
* try all of them in order and use the first one that
@@ -1778,7 +1771,7 @@ _public_ void sd_bus_close(sd_bus *bus) {
return;
/* Don't leave ssh hanging around */
bus_kill_exec(bus);
pidref_done_sigterm_wait(&bus->busexec_pidref);
bus_set_state(bus, BUS_CLOSED);
@@ -1809,7 +1802,7 @@ _public_ sd_bus* sd_bus_flush_close_unref(sd_bus *bus) {
return NULL;
/* Have to do this before flush() to prevent hang */
bus_kill_exec(bus);
pidref_done_sigterm_wait(&bus->busexec_pidref);
sd_bus_flush(bus);
return sd_bus_close_unref(bus);
+17 -17
View File
@@ -26,6 +26,7 @@
#include "mkdir.h"
#include "path-util.h"
#include "pidfd-util.h"
#include "pidref.h"
#include "process-util.h"
#include "socket-util.h"
#include "string-table.h"
@@ -149,6 +150,8 @@ static int varlink_new(sd_varlink **ret) {
.allow_fd_passing_input = -1,
.af = -1,
.exec_pidref = PIDREF_NULL,
};
*ret = v;
@@ -209,7 +212,7 @@ _public_ int sd_varlink_connect_address(sd_varlink **ret, const char *address) {
_public_ int sd_varlink_connect_exec(sd_varlink **ret, const char *_command, char **_argv) {
_cleanup_close_pair_ int pair[2] = EBADF_PAIR;
_cleanup_(sigkill_waitp) pid_t pid = 0;
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
_cleanup_free_ char *command = NULL;
_cleanup_strv_free_ char **argv = NULL;
int r;
@@ -239,13 +242,13 @@ _public_ int sd_varlink_connect_exec(sd_varlink **ret, const char *_command, cha
if (r < 0)
return log_debug_errno(r, "Failed to disable O_NONBLOCK for varlink socket: %m");
r = safe_fork_full(
r = pidref_safe_fork_full(
"(sd-vlexec)",
/* stdio_fds= */ NULL,
/* except_fds= */ (int[]) { pair[1] },
/* n_except_fds= */ 1,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
&pid);
&pidref);
if (r < 0)
return log_debug_errno(r, "Failed to spawn process: %m");
if (r == 0) {
@@ -266,7 +269,7 @@ _public_ int sd_varlink_connect_exec(sd_varlink **ret, const char *_command, cha
_exit(EXIT_FAILURE);
}
xsprintf(spid, PID_FMT, pid);
xsprintf(spid, PID_FMT, pidref.pid);
uint64_t pidfdid;
if (pidfd_get_inode_id_self_cached(&pidfdid) >= 0) {
@@ -298,7 +301,7 @@ _public_ int sd_varlink_connect_exec(sd_varlink **ret, const char *_command, cha
v->output_fd = v->input_fd = TAKE_FD(pair[0]);
v->af = AF_UNIX;
v->exec_pid = TAKE_PID(pid);
v->exec_pidref = TAKE_PIDREF(pidref);
varlink_set_state(v, VARLINK_IDLE_CLIENT);
*ret = v;
@@ -318,7 +321,7 @@ static int ssh_path(const char **ret) {
static int varlink_connect_ssh_unix(sd_varlink **ret, const char *where) {
_cleanup_close_pair_ int pair[2] = EBADF_PAIR;
_cleanup_(sigkill_waitp) pid_t pid = 0;
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
int r;
assert_return(ret, -EINVAL);
@@ -356,13 +359,13 @@ static int varlink_connect_ssh_unix(sd_varlink **ret, const char *where) {
if (socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0, pair) < 0)
return log_debug_errno(errno, "Failed to allocate AF_UNIX socket pair: %m");
r = safe_fork_full(
r = pidref_safe_fork_full(
"(sd-vlssh)",
/* stdio_fds= */ (int[]) { pair[1], pair[1], STDERR_FILENO },
/* except_fds= */ NULL,
/* n_except_fds= */ 0,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO,
&pid);
&pidref);
if (r < 0)
return log_debug_errno(r, "Failed to spawn process: %m");
if (r == 0) {
@@ -382,7 +385,7 @@ static int varlink_connect_ssh_unix(sd_varlink **ret, const char *where) {
v->output_fd = v->input_fd = TAKE_FD(pair[0]);
v->af = AF_UNIX;
v->exec_pid = TAKE_PID(pid);
v->exec_pidref = TAKE_PIDREF(pidref);
varlink_set_state(v, VARLINK_IDLE_CLIENT);
*ret = v;
@@ -391,7 +394,7 @@ static int varlink_connect_ssh_unix(sd_varlink **ret, const char *where) {
static int varlink_connect_ssh_exec(sd_varlink **ret, const char *where) {
_cleanup_close_pair_ int input_pipe[2] = EBADF_PAIR, output_pipe[2] = EBADF_PAIR;
_cleanup_(sigkill_waitp) pid_t pid = 0;
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
int r;
assert_return(ret, -EINVAL);
@@ -440,13 +443,13 @@ static int varlink_connect_ssh_exec(sd_varlink **ret, const char *where) {
if (pipe2(output_pipe, O_CLOEXEC) < 0)
return log_debug_errno(errno, "Failed to allocate output pipe: %m");
r = safe_fork_full(
r = pidref_safe_fork_full(
"(sd-vlssh)",
/* stdio_fds= */ (int[]) { input_pipe[0], output_pipe[1], STDERR_FILENO },
/* except_fds= */ NULL,
/* n_except_fds= */ 0,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO,
&pid);
&pidref);
if (r < 0)
return log_debug_errno(r, "Failed to spawn process: %m");
if (r == 0) {
@@ -475,7 +478,7 @@ static int varlink_connect_ssh_exec(sd_varlink **ret, const char *where) {
v->input_fd = TAKE_FD(output_pipe[0]);
v->output_fd = TAKE_FD(input_pipe[1]);
v->af = AF_UNSPEC;
v->exec_pid = TAKE_PID(pid);
v->exec_pidref = TAKE_PIDREF(pidref);
varlink_set_state(v, VARLINK_IDLE_CLIENT);
*ret = v;
@@ -648,10 +651,7 @@ static void varlink_clear(sd_varlink *v) {
v->event = sd_event_unref(v->event);
if (v->exec_pid > 0) {
sigterm_wait(v->exec_pid);
v->exec_pid = 0;
}
pidref_done_sigterm_wait(&v->exec_pidref);
v->peer_pidfd = safe_close(v->peer_pidfd);
}
+2 -1
View File
@@ -6,6 +6,7 @@
#include "sd-varlink.h"
#include "list.h"
#include "pidref.h"
#include "sd-forward.h"
typedef enum VarlinkState {
@@ -187,7 +188,7 @@ struct sd_varlink {
sd_event_source *quit_event_source;
sd_event_source *defer_event_source;
pid_t exec_pid;
PidRef exec_pidref;
};
typedef struct VarlinkServerSocket VarlinkServerSocket;
+4 -3
View File
@@ -20,6 +20,7 @@
#include "main-func.h"
#include "pager.h"
#include "parse-argument.h"
#include "pidref.h"
#include "polkit-agent.h"
#include "pretty-print.h"
#include "process-util.h"
@@ -330,7 +331,6 @@ static int run(int argc, char *argv[]) {
_cleanup_strv_free_ char **arguments = NULL;
_cleanup_free_ char *w = NULL;
_cleanup_close_ int fd = -EBADF;
pid_t pid;
/* Ignore SIGINT and allow the forked process to receive it */
(void) ignore_signals(SIGINT);
@@ -360,7 +360,8 @@ static int run(int argc, char *argv[]) {
if (!arguments)
return log_oom();
r = safe_fork("(inhibit)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = pidref_safe_fork("(inhibit)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pidref);
if (r < 0)
return r;
if (r == 0) {
@@ -371,7 +372,7 @@ static int run(int argc, char *argv[]) {
_exit(EXIT_FAILURE);
}
return wait_for_terminate_and_check(argv[optind], pid, WAIT_LOG);
return pidref_wait_for_terminate_and_check(argv[optind], &pidref, WAIT_LOG);
}
}
+12 -12
View File
@@ -32,7 +32,7 @@ int bus_image_method_remove(
_cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR;
Image *image = ASSERT_PTR(userdata);
Manager *m = image->userdata;
pid_t child;
_cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL;
int r;
assert(message);
@@ -62,7 +62,7 @@ int bus_image_method_remove(
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
r = safe_fork("(sd-imgrm)", FORK_RESET_SIGNALS, &child);
r = pidref_safe_fork("(sd-imgrm)", FORK_RESET_SIGNALS, &child);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
if (r == 0) {
@@ -73,11 +73,11 @@ int bus_image_method_remove(
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
r = operation_new_with_bus_reply(m, /* machine= */ NULL, child, message, errno_pipe_fd[0], /* ret= */ NULL);
if (r < 0) {
sigkill_wait(child);
r = operation_new_with_bus_reply(m, /* machine= */ NULL, &child, message, errno_pipe_fd[0], /* ret= */ NULL);
if (r < 0)
return r;
}
TAKE_PIDREF(child);
errno_pipe_fd[0] = -EBADF;
@@ -140,7 +140,7 @@ int bus_image_method_clone(
Manager *m = ASSERT_PTR(image->userdata);
const char *new_name;
int r, read_only;
pid_t child;
_cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL;
assert(message);
@@ -177,7 +177,7 @@ int bus_image_method_clone(
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
r = safe_fork("(sd-imgclone)", FORK_RESET_SIGNALS, &child);
r = pidref_safe_fork("(sd-imgclone)", FORK_RESET_SIGNALS, &child);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
if (r == 0) {
@@ -188,11 +188,11 @@ int bus_image_method_clone(
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
r = operation_new_with_bus_reply(m, /* machine= */ NULL, child, message, errno_pipe_fd[0], /* ret= */ NULL);
if (r < 0) {
sigkill_wait(child);
r = operation_new_with_bus_reply(m, /* machine= */ NULL, &child, message, errno_pipe_fd[0], /* ret= */ NULL);
if (r < 0)
return r;
}
TAKE_PIDREF(child);
errno_pipe_fd[0] = -EBADF;
+10 -12
View File
@@ -115,7 +115,7 @@ int vl_method_clone_image(sd_varlink *link, sd_json_variant *parameters, sd_varl
_cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR;
ImageUpdateParameters p = IMAGE_UPDATE_PARAMETERS_NULL;
Image *image;
pid_t child;
_cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL;
int r;
assert(link);
@@ -156,7 +156,7 @@ int vl_method_clone_image(sd_varlink *link, sd_json_variant *parameters, sd_varl
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
return log_debug_errno(errno, "Failed to open pipe: %m");
r = safe_fork("(sd-imgclone)", FORK_RESET_SIGNALS, &child);
r = pidref_safe_fork("(sd-imgclone)", FORK_RESET_SIGNALS, &child);
if (r < 0)
return log_debug_errno(r, "Failed to fork: %m");
if (r == 0) {
@@ -167,12 +167,11 @@ int vl_method_clone_image(sd_varlink *link, sd_json_variant *parameters, sd_varl
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
r = operation_new_with_varlink_reply(manager, /* machine= */ NULL, child, link, errno_pipe_fd[0], /* ret= */ NULL);
if (r < 0) {
sigkill_wait(child);
r = operation_new_with_varlink_reply(manager, /* machine= */ NULL, &child, link, errno_pipe_fd[0], /* ret= */ NULL);
if (r < 0)
return r;
}
TAKE_PIDREF(child);
TAKE_FD(errno_pipe_fd[0]);
return 1;
}
@@ -188,7 +187,7 @@ int vl_method_remove_image(sd_varlink *link, sd_json_variant *parameters, sd_var
_cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR;
const char *image_name;
Image *image;
pid_t child;
_cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL;
int r;
assert(link);
@@ -225,7 +224,7 @@ int vl_method_remove_image(sd_varlink *link, sd_json_variant *parameters, sd_var
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
return log_debug_errno(errno, "Failed to open pipe: %m");
r = safe_fork("(sd-imgrm)", FORK_RESET_SIGNALS, &child);
r = pidref_safe_fork("(sd-imgrm)", FORK_RESET_SIGNALS, &child);
if (r < 0)
return log_debug_errno(r, "Failed to fork: %m");
if (r == 0) {
@@ -236,12 +235,11 @@ int vl_method_remove_image(sd_varlink *link, sd_json_variant *parameters, sd_var
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
r = operation_new_with_varlink_reply(manager, /* machine= */ NULL, child, link, errno_pipe_fd[0], /* ret= */ NULL);
if (r < 0) {
sigkill_wait(child);
r = operation_new_with_varlink_reply(manager, /* machine= */ NULL, &child, link, errno_pipe_fd[0], /* ret= */ NULL);
if (r < 0)
return r;
}
TAKE_PIDREF(child);
TAKE_FD(errno_pipe_fd[0]);
return 1;
}
+4 -4
View File
@@ -96,7 +96,7 @@ int clean_pool_read_next_entry(FILE *file, char **ret_name, uint64_t *ret_usage)
int image_clean_pool_operation(Manager *manager, ImageCleanPoolMode mode, Operation **ret_operation) {
_cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR;
_cleanup_close_ int result_fd = -EBADF;
_cleanup_(sigkill_waitp) pid_t child = 0;
_cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL;
int r;
assert(manager);
@@ -113,7 +113,7 @@ int image_clean_pool_operation(Manager *manager, ImageCleanPoolMode mode, Operat
return log_debug_errno(result_fd, "Failed to open tmpfile: %m");
/* This might be a slow operation, run it asynchronously in a background process */
r = safe_fork("(sd-clean)", FORK_RESET_SIGNALS, &child);
r = pidref_safe_fork("(sd-clean)", FORK_RESET_SIGNALS, &child);
if (r < 0)
return log_debug_errno(r, "Failed to fork(): %m");
if (r == 0) {
@@ -183,13 +183,13 @@ int image_clean_pool_operation(Manager *manager, ImageCleanPoolMode mode, Operat
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
/* The clean-up might take a while, hence install a watch on the child and return */
r = operation_new(manager, /* machine= */ NULL, child, errno_pipe_fd[0], ret_operation);
r = operation_new(manager, /* machine= */ NULL, &child, errno_pipe_fd[0], ret_operation);
if (r < 0)
return r;
(*ret_operation)->extra_fd = TAKE_FD(result_fd);
TAKE_FD(errno_pipe_fd[0]);
TAKE_PID(child);
TAKE_PIDREF(child);
return 0;
}
+1 -1
View File
@@ -1244,7 +1244,7 @@ int machine_copy_from_to_operation(
// TODO: port to PidRef and donate child rather than destroying it
Operation *operation;
r = operation_new(manager, machine, child.pid, errno_pipe_fd[0], &operation);
r = operation_new(manager, machine, &child, errno_pipe_fd[0], &operation);
if (r < 0)
return r;
+9 -9
View File
@@ -8,6 +8,7 @@
#include "sd-varlink.h"
#include "alloc-util.h"
#include "event-util.h"
#include "fd-util.h"
#include "format-util.h"
#include "log.h"
@@ -45,10 +46,10 @@ static int operation_done(sd_event_source *s, const siginfo_t *si, void *userdat
assert(si);
log_debug("Operation " PID_FMT " is now complete with code=%s status=%i",
o->pid,
o->pidref.pid,
sigchld_code_to_string(si->si_code), si->si_status);
o->pid = 0;
pidref_done(&o->pidref);
r = read_operation_errno(si, o);
if (r < 0)
@@ -96,12 +97,12 @@ static int operation_done(sd_event_source *s, const siginfo_t *si, void *userdat
return 0;
}
int operation_new(Manager *manager, Machine *machine, pid_t child, int errno_fd, Operation **ret) {
int operation_new(Manager *manager, Machine *machine, PidRef *child, int errno_fd, Operation **ret) {
Operation *o;
int r;
assert(manager);
assert(child > 1);
assert(pidref_is_set(child));
assert(errno_fd >= 0);
assert(ret);
@@ -110,12 +111,12 @@ int operation_new(Manager *manager, Machine *machine, pid_t child, int errno_fd,
return -ENOMEM;
*o = (Operation) {
.pid = child,
.pidref = TAKE_PIDREF(*child),
.errno_fd = errno_fd,
.extra_fd = -EBADF
};
r = sd_event_add_child(manager->event, &o->event_source, child, WEXITED, operation_done, o);
r = event_add_child_pidref(manager->event, &o->event_source, &o->pidref, WEXITED, operation_done, o);
if (r < 0) {
free(o);
return r;
@@ -130,7 +131,7 @@ int operation_new(Manager *manager, Machine *machine, pid_t child, int errno_fd,
o->machine = machine;
}
log_debug("Started new operation " PID_FMT ".", child);
log_debug("Started new operation " PID_FMT ".", o->pidref.pid);
/* At this point we took ownership of both the child and the errno file descriptor! */
@@ -147,8 +148,7 @@ Operation *operation_free(Operation *o) {
safe_close(o->errno_fd);
safe_close(o->extra_fd);
if (o->pid > 1)
sigkill_wait(o->pid);
pidref_done_sigkill_wait(&o->pidref);
sd_bus_message_unref(o->message);
sd_varlink_unref(o->link);
+5 -4
View File
@@ -3,13 +3,14 @@
#include "list.h"
#include "machine-forward.h"
#include "pidref.h"
#define OPERATIONS_MAX 64
typedef struct Operation {
Manager *manager;
Machine *machine;
pid_t pid;
PidRef pidref;
/* only one of these two fields should be set */
sd_varlink *link;
@@ -23,7 +24,7 @@ typedef struct Operation {
LIST_FIELDS(Operation, operations_by_machine);
} Operation;
int operation_new(Manager *manager, Machine *machine, pid_t child, int errno_fd, Operation **ret);
int operation_new(Manager *manager, Machine *machine, PidRef *child, int errno_fd, Operation **ret);
Operation *operation_free(Operation *o);
void operation_attach_bus_reply(Operation *op, sd_bus_message *message);
@@ -32,7 +33,7 @@ void operation_attach_varlink_reply(Operation *op, sd_varlink *link);
static inline int operation_new_with_bus_reply(
Manager *manager,
Machine *machine,
pid_t child,
PidRef *child,
sd_bus_message *message,
int errno_fd,
Operation **ret) {
@@ -55,7 +56,7 @@ static inline int operation_new_with_bus_reply(
static inline int operation_new_with_varlink_reply(
Manager *manager,
Machine *machine,
pid_t child,
PidRef *child,
sd_varlink *link,
int errno_fd,
Operation **ret) {
+16 -13
View File
@@ -11,26 +11,28 @@
#include "log.h"
#include "mkdir.h"
#include "nspawn-setuid.h"
#include "pidref.h"
#include "process-util.h"
#include "string-util.h"
#include "strv.h"
#include "user-util.h"
static int spawn_getent(const char *database, const char *key, pid_t *rpid) {
static int spawn_getent(const char *database, const char *key, PidRef *ret) {
int pipe_fds[2], r;
pid_t pid;
assert(database);
assert(key);
assert(rpid);
assert(ret);
if (pipe2(pipe_fds, O_CLOEXEC) < 0)
return log_error_errno(errno, "Failed to allocate pipe: %m");
r = safe_fork_full("(getent)",
(int[]) { -EBADF, pipe_fds[1], -EBADF }, NULL, 0,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
&pid);
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = pidref_safe_fork_full(
"(getent)",
(int[]) { -EBADF, pipe_fds[1], -EBADF }, NULL, 0,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
&pidref);
if (r < 0) {
safe_close_pair(pipe_fds);
return r;
@@ -43,7 +45,7 @@ static int spawn_getent(const char *database, const char *key, pid_t *rpid) {
pipe_fds[1] = safe_close(pipe_fds[1]);
*rpid = pid;
*ret = TAKE_PIDREF(pidref);
return pipe_fds[0];
}
@@ -84,7 +86,6 @@ int change_uid_gid(const char *user, bool chown_stdio, char **ret_home) {
unsigned n_gids = 0;
uid_t uid;
gid_t gid;
pid_t pid;
int r;
assert(ret_home);
@@ -101,7 +102,8 @@ int change_uid_gid(const char *user, bool chown_stdio, char **ret_home) {
}
/* First, get user credentials */
fd = spawn_getent("passwd", user, &pid);
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
fd = spawn_getent("passwd", user, &pidref);
if (fd < 0)
return fd;
@@ -116,7 +118,7 @@ int change_uid_gid(const char *user, bool chown_stdio, char **ret_home) {
if (r < 0)
return log_error_errno(r, "Failed to read from getent: %m");
(void) wait_for_terminate_and_check("getent passwd", pid, WAIT_LOG);
(void) pidref_wait_for_terminate_and_check("getent passwd", &pidref, WAIT_LOG);
x = strchr(line, ':');
if (!x)
@@ -173,7 +175,8 @@ int change_uid_gid(const char *user, bool chown_stdio, char **ret_home) {
line = mfree(line);
/* Second, get group memberships */
fd = spawn_getent("initgroups", user, &pid);
pidref_done(&pidref);
fd = spawn_getent("initgroups", user, &pidref);
if (fd < 0)
return fd;
@@ -188,7 +191,7 @@ int change_uid_gid(const char *user, bool chown_stdio, char **ret_home) {
if (r < 0)
return log_error_errno(r, "Failed to read from getent: %m");
(void) wait_for_terminate_and_check("getent initgroups", pid, WAIT_LOG);
(void) pidref_wait_for_terminate_and_check("getent initgroups", &pidref, WAIT_LOG);
/* Skip over the username and subsequent separator whitespace */
x = line;
+1 -1
View File
@@ -2884,7 +2884,7 @@ static int recursive_chown(const char *directory, uid_t shift, uid_t range) {
/*
* Return values:
* < 0 : wait_for_terminate() failed to get the state of the
* < 0 : pidref_wait_for_terminate() failed to get the state of the
* container, the container was terminated by a signal, or
* failed for an unknown reason. No change is made to the
* container argument.
+4 -4
View File
@@ -541,7 +541,7 @@ static int allocate_now(
}
static int write_userns(int usernsfd, const UserNamespaceInfo *userns_info) {
_cleanup_(sigkill_waitp) pid_t pid = 0;
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
_cleanup_close_ int efd = -EBADF;
uint64_t u;
int r;
@@ -560,7 +560,7 @@ static int write_userns(int usernsfd, const UserNamespaceInfo *userns_info) {
if (efd < 0)
return log_error_errno(errno, "Failed to allocate eventfd(): %m");
r = safe_fork("(sd-userns)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_LOG, &pid);
r = pidref_safe_fork("(sd-userns)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_LOG, &pidref);
if (r < 0)
return r;
if (r == 0) {
@@ -590,7 +590,7 @@ static int write_userns(int usernsfd, const UserNamespaceInfo *userns_info) {
_cleanup_free_ char *pmap = NULL;
if (asprintf(&pmap, "/proc/" PID_FMT "/uid_map", pid) < 0)
if (asprintf(&pmap, "/proc/" PID_FMT "/uid_map", pidref.pid) < 0)
return log_oom();
r = write_string_filef(pmap, 0, UID_FMT " " UID_FMT " %" PRIu32 "\n", userns_info->target_uid, userns_info->start_uid, userns_info->size);
@@ -598,7 +598,7 @@ static int write_userns(int usernsfd, const UserNamespaceInfo *userns_info) {
return log_error_errno(r, "Failed to write 'uid_map' file of user namespace: %m");
pmap = mfree(pmap);
if (asprintf(&pmap, "/proc/" PID_FMT "/gid_map", pid) < 0)
if (asprintf(&pmap, "/proc/" PID_FMT "/gid_map", pidref.pid) < 0)
return log_oom();
r = write_string_filef(pmap, 0, GID_FMT " " GID_FMT " %" PRIu32 "\n", userns_info->target_gid, userns_info->start_gid, userns_info->size);
+4 -3
View File
@@ -11,6 +11,7 @@
#include "log.h"
#include "main-func.h"
#include "namespace-util.h"
#include "pidref.h"
#include "process-util.h"
#include "rm-rf.h"
#include "tmpfile-util.h"
@@ -56,7 +57,7 @@ static int run(int argc, char *argv[]) {
_cleanup_(userns_restrict_bpf_freep) struct userns_restrict_bpf *obj = NULL;
_cleanup_close_ int userns_fd = -EBADF, host_fd1 = -EBADF, host_tmpfs = -EBADF, afd = -EBADF, bfd = -EBADF;
_cleanup_(rm_rf_physical_and_freep) char *t = NULL;
_cleanup_(sigkill_waitp) pid_t pid = 0;
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
int r;
log_set_max_level(LOG_DEBUG);
@@ -100,7 +101,7 @@ static int run(int argc, char *argv[]) {
assert_se(afd >= 0 && bfd >= 0);
r = safe_fork("(test)", FORK_DEATHSIG_SIGKILL, &pid);
r = pidref_safe_fork("(test)", FORK_DEATHSIG_SIGKILL, &pidref);
assert_se(r >= 0);
if (r == 0) {
_cleanup_close_ int private_tmpfs = -EBADF;
@@ -178,7 +179,7 @@ static int run(int argc, char *argv[]) {
assert_se(eventfd_write(bfd, 1) >= 0);
assert_se(wait_for_terminate_and_check("(test)", pid, WAIT_LOG) >= 0);
assert_se(pidref_wait_for_terminate_and_check("(test)", &pidref, WAIT_LOG) >= 0);
return 0;
}
+6 -7
View File
@@ -36,13 +36,13 @@
#include "mkdir.h"
#include "os-util.h"
#include "path-lookup.h"
#include "pidref.h"
#include "portable.h"
#include "portable-util.h"
#include "process-util.h"
#include "rm-rf.h"
#include "selinux-util.h"
#include "set.h"
#include "signal-util.h"
#include "socket-util.h"
#include "sort-util.h"
#include "string-table.h"
@@ -400,7 +400,7 @@ static int portable_extract_by_path(
_cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
_cleanup_(rmdir_and_freep) char *tmpdir = NULL;
_cleanup_close_pair_ int seq[2] = EBADF_PAIR;
_cleanup_(sigkill_waitp) pid_t child = 0;
_cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL;
DissectImageFlags flags =
DISSECT_IMAGE_READ_ONLY |
DISSECT_IMAGE_GENERIC_ROOT |
@@ -420,8 +420,6 @@ static int portable_extract_by_path(
/* We now have a loopback block device, let's fork off a child in its own mount namespace, mount it
* there, and extract the metadata we need. The metadata is sent from the child back to us. */
BLOCK_SIGNALS(SIGCHLD);
/* Load some libraries before we fork workers off that want to use them */
(void) dlopen_cryptsetup();
(void) dlopen_libmount();
@@ -454,7 +452,7 @@ static int portable_extract_by_path(
if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, seq) < 0)
return log_debug_errno(errno, "Failed to allocated SOCK_SEQPACKET socket: %m");
r = safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_LOG, &child);
r = pidref_safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_LOG, &child);
if (r < 0)
return r;
if (r == 0) {
@@ -540,10 +538,11 @@ static int portable_extract_by_path(
assert_not_reached();
}
r = wait_for_terminate_and_check("(sd-dissect)", child, 0);
r = pidref_wait_for_terminate_and_check("(sd-dissect)", &child, 0);
if (r < 0)
return r;
child = 0;
TAKE_PIDREF(child);
}
if (!os_release)
+4 -4
View File
@@ -488,7 +488,7 @@ int bus_image_common_remove(
sd_bus_error *error) {
_cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR;
_cleanup_(sigkill_waitp) pid_t child = 0;
_cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL;
PortableState state;
int r;
@@ -533,7 +533,7 @@ int bus_image_common_remove(
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
r = safe_fork("(sd-imgrm)", FORK_RESET_SIGNALS, &child);
r = pidref_safe_fork("(sd-imgrm)", FORK_RESET_SIGNALS, &child);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
if (r == 0) {
@@ -550,11 +550,11 @@ int bus_image_common_remove(
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
r = operation_new(m, child, message, errno_pipe_fd[0], NULL);
r = operation_new(m, &child, message, errno_pipe_fd[0], NULL);
if (r < 0)
return r;
child = 0;
TAKE_PIDREF(child);
errno_pipe_fd[0] = -EBADF;
return 1;
+9 -9
View File
@@ -7,6 +7,7 @@
#include "sd-event.h"
#include "alloc-util.h"
#include "event-util.h"
#include "fd-util.h"
#include "format-util.h"
#include "log.h"
@@ -22,10 +23,10 @@ static int operation_done(sd_event_source *s, const siginfo_t *si, void *userdat
assert(si);
log_debug("Operation " PID_FMT " is now complete with code=%s status=%i",
o->pid,
o->pidref.pid,
sigchld_code_to_string(si->si_code), si->si_status);
o->pid = 0;
pidref_done(&o->pidref);
if (si->si_code != CLD_EXITED) {
r = sd_bus_error_set(&error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
@@ -74,12 +75,12 @@ fail:
return 0;
}
int operation_new(Manager *manager, pid_t child, sd_bus_message *message, int errno_fd, Operation **ret) {
int operation_new(Manager *manager, PidRef *child, sd_bus_message *message, int errno_fd, Operation **ret) {
Operation *o;
int r;
assert(manager);
assert(child > 1);
assert(pidref_is_set(child));
assert(message);
assert(errno_fd >= 0);
@@ -89,13 +90,13 @@ int operation_new(Manager *manager, pid_t child, sd_bus_message *message, int er
o->extra_fd = -EBADF;
r = sd_event_add_child(manager->event, &o->event_source, child, WEXITED, operation_done, o);
r = event_add_child_pidref(manager->event, &o->event_source, child, WEXITED, operation_done, o);
if (r < 0) {
free(o);
return r;
}
o->pid = child;
o->pidref = TAKE_PIDREF(*child);
o->message = sd_bus_message_ref(message);
o->errno_fd = errno_fd;
@@ -103,7 +104,7 @@ int operation_new(Manager *manager, pid_t child, sd_bus_message *message, int er
manager->n_operations++;
o->manager = manager;
log_debug("Started new operation " PID_FMT ".", child);
log_debug("Started new operation " PID_FMT ".", o->pidref.pid);
/* At this point we took ownership of both the child and the errno file descriptor! */
@@ -122,8 +123,7 @@ Operation *operation_free(Operation *o) {
safe_close(o->errno_fd);
safe_close(o->extra_fd);
if (o->pid > 1)
sigkill_wait(o->pid);
pidref_done_sigkill_wait(&o->pidref);
sd_bus_message_unref(o->message);
+3 -2
View File
@@ -2,13 +2,14 @@
#pragma once
#include "list.h"
#include "pidref.h"
#include "portabled-forward.h"
#define OPERATIONS_MAX 64
typedef struct Operation {
Manager *manager;
pid_t pid;
PidRef pidref;
sd_bus_message *message;
int errno_fd;
int extra_fd;
@@ -17,5 +18,5 @@ typedef struct Operation {
LIST_FIELDS(Operation, operations);
} Operation;
int operation_new(Manager *manager, pid_t child, sd_bus_message *message, int errno_fd, Operation **ret);
int operation_new(Manager *manager, PidRef *child, sd_bus_message *message, int errno_fd, Operation **ret);
Operation *operation_free(Operation *o);
+5 -11
View File
@@ -1,19 +1,17 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <signal.h>
#include "ask-password-agent.h"
#include "bus-util.h"
#include "exec-util.h"
#include "log.h"
#include "process-util.h"
#include "pidref.h"
static pid_t agent_pid = 0;
static PidRef agent_pidref = PIDREF_NULL;
int ask_password_agent_open(void) {
int r;
if (agent_pid > 0)
if (pidref_is_set(&agent_pidref))
return 0;
r = shall_fork_agent();
@@ -22,7 +20,7 @@ int ask_password_agent_open(void) {
r = fork_agent("(sd-askpwagent)",
NULL, 0,
&agent_pid,
&agent_pidref,
SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH,
"--watch");
if (r < 0)
@@ -32,12 +30,8 @@ int ask_password_agent_open(void) {
}
void ask_password_agent_close(void) {
if (agent_pid <= 0)
return;
/* Inform agent that we are done */
sigterm_wait(TAKE_PID(agent_pid));
pidref_done_sigterm_wait(&agent_pidref);
}
int ask_password_agent_open_if_enabled(BusTransport transport, bool ask_password) {
+10 -11
View File
@@ -59,11 +59,11 @@
#include "openssl-util.h"
#include "os-util.h"
#include "path-util.h"
#include "pidref.h"
#include "proc-cmdline.h"
#include "process-util.h"
#include "resize-fs.h"
#include "runtime-scope.h"
#include "signal-util.h"
#include "siphash24.h"
#include "stat-util.h"
#include "string-util.h"
@@ -2237,7 +2237,6 @@ static int is_loop_device(const char *path) {
static int run_fsck(int node_fd, const char *fstype) {
int r, exit_status;
pid_t pid;
assert(node_fd >= 0);
assert(fstype);
@@ -2252,12 +2251,13 @@ static int run_fsck(int node_fd, const char *fstype) {
return 0;
}
r = safe_fork_full(
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = pidref_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_SIGTERM|FORK_REARRANGE_STDIO|FORK_CLOEXEC_OFF,
&pid);
&pidref);
if (r < 0)
return log_debug_errno(r, "Failed to fork off fsck: %m");
if (r == 0) {
@@ -2268,7 +2268,7 @@ static int run_fsck(int node_fd, const char *fstype) {
_exit(FSCK_OPERATIONAL_ERROR);
}
exit_status = wait_for_terminate_and_check("fsck", pid, 0);
exit_status = pidref_wait_for_terminate_and_check("fsck", &pidref, 0);
if (exit_status < 0)
return log_debug_errno(exit_status, "Failed to fork off fsck: %m");
@@ -4170,15 +4170,13 @@ int dissected_image_acquire_metadata(
_cleanup_strv_free_ char **machine_info = NULL, **os_release = NULL, **initrd_release = NULL, **sysext_release = NULL, **confext_release = NULL;
_cleanup_free_ char *hostname = NULL, *t = NULL;
_cleanup_close_pair_ int error_pipe[2] = EBADF_PAIR;
_cleanup_(sigkill_waitp) pid_t child = 0;
_cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL;
sd_id128_t machine_id = SD_ID128_NULL;
unsigned n_meta_initialized = 0;
int fds[2 * _META_MAX], r, v;
int has_init_system = -1;
ssize_t n;
BLOCK_SIGNALS(SIGCHLD);
assert(m);
r = dlopen_libmount();
@@ -4203,7 +4201,7 @@ int dissected_image_acquire_metadata(
goto finish;
}
r = safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM, &child);
r = pidref_safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM, &child);
if (r < 0)
goto finish;
if (r == 0) {
@@ -4426,11 +4424,12 @@ int dissected_image_acquire_metadata(
}}
}
r = wait_for_terminate_and_check("(sd-dissect)", child, 0);
child = 0;
r = pidref_wait_for_terminate_and_check("(sd-dissect)", &child, 0);
if (r < 0)
goto finish;
TAKE_PIDREF(child);
n = read(error_pipe[0], &v, sizeof(v));
if (n < 0) {
r = -errno;
+35 -25
View File
@@ -17,6 +17,7 @@
#include "hashmap.h"
#include "log.h"
#include "path-util.h"
#include "pidref.h"
#include "process-util.h"
#include "serialize.h"
#include "stat-util.h"
@@ -28,6 +29,10 @@
#define EXIT_SKIP_REMAINING 77
DEFINE_PRIVATE_HASH_OPS_FULL(pidref_hash_ops_free_free,
PidRef, pidref_hash_func, pidref_compare_func,
pidref_free, char*, free);
/* Put this test here for a lack of better place */
assert_cc(EAGAIN == EWOULDBLOCK);
@@ -36,25 +41,25 @@ static int do_spawn(
char *argv[],
int stdout_fd,
bool set_systemd_exec_pid,
pid_t *ret_pid) {
PidRef *ret) {
int r;
assert(path);
assert(ret_pid);
assert(ret);
if (null_or_empty_path(path) > 0) {
log_debug("%s is masked, skipping.", path);
return 0;
}
pid_t pid;
r = safe_fork_full(
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = pidref_safe_fork_full(
"(exec-inner)",
(const int[]) { STDIN_FILENO, stdout_fd < 0 ? STDOUT_FILENO : stdout_fd, STDERR_FILENO },
/* except_fds= */ NULL, /* n_except_fds= */ 0,
FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO|FORK_CLOSE_ALL_FDS,
&pid);
&pidref);
if (r < 0)
return r;
if (r == 0) {
@@ -78,7 +83,7 @@ static int do_spawn(
_exit(EXIT_FAILURE);
}
*ret_pid = pid;
*ret = TAKE_PIDREF(pidref);
return 1;
}
@@ -121,7 +126,6 @@ static int do_execute(
STRV_FOREACH(path, paths) {
_cleanup_free_ char *t = NULL;
_cleanup_close_ int fd = -EBADF;
pid_t pid;
t = path_join(root, *path);
if (!t)
@@ -161,19 +165,27 @@ static int do_execute(
"permission bits. Proceeding anyway.", t);
}
r = do_spawn(t, argv, fd, FLAGS_SET(flags, EXEC_DIR_SET_SYSTEMD_EXEC_PID), &pid);
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = do_spawn(t, argv, fd, FLAGS_SET(flags, EXEC_DIR_SET_SYSTEMD_EXEC_PID), &pidref);
if (r <= 0)
continue;
if (parallel_execution) {
r = hashmap_ensure_put(&pids, &trivial_hash_ops_value_free, PID_TO_PTR(pid), t);
_cleanup_(pidref_freep) PidRef *dup = NULL;
r = pidref_dup(&pidref, &dup);
if (r < 0)
return r;
r = hashmap_ensure_put(&pids, &pidref_hash_ops_free_free, dup, t);
if (r < 0)
return log_oom();
t = NULL;
TAKE_PTR(dup);
TAKE_PTR(t);
} else {
bool skip_remaining = false;
r = wait_for_terminate_and_check(t, pid, WAIT_LOG_ABNORMAL);
r = pidref_wait_for_terminate_and_check(t, &pidref, WAIT_LOG_ABNORMAL);
if (r < 0)
return r;
if (r > 0) {
@@ -211,14 +223,12 @@ static int do_execute(
while (!hashmap_isempty(pids)) {
_cleanup_free_ char *t = NULL;
pid_t pid;
void *p;
t = ASSERT_PTR(hashmap_steal_first_key_and_value(pids, &p));
pid = PTR_TO_PID(p);
assert(pid > 0);
_cleanup_(pidref_freep) PidRef *pidref = p;
r = wait_for_terminate_and_check(t, pid, WAIT_LOG);
r = pidref_wait_for_terminate_and_check(t, pidref, WAIT_LOG);
if (r < 0)
return r;
if (!FLAGS_SET(flags, EXEC_DIR_IGNORE_ERRORS) && r > 0)
@@ -240,7 +250,6 @@ int execute_strv(
ExecDirFlags flags) {
_cleanup_close_ int fd = -EBADF;
pid_t executor_pid;
int r;
assert(name);
@@ -266,7 +275,8 @@ int execute_strv(
const char *process_name = strjoina("(", name, ")");
r = safe_fork(process_name, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG, &executor_pid);
PidRef executor_pidref = PIDREF_NULL;
r = pidref_safe_fork(process_name, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG, &executor_pidref);
if (r < 0)
return r;
if (r == 0) {
@@ -274,7 +284,7 @@ int execute_strv(
_exit(r < 0 ? EXIT_FAILURE : r);
}
r = wait_for_terminate_and_check(process_name, executor_pid, 0);
r = pidref_wait_for_terminate_and_check(process_name, &executor_pidref, 0);
if (r < 0)
return r;
if (!FLAGS_SET(flags, EXEC_DIR_IGNORE_ERRORS) && r > 0)
@@ -560,19 +570,19 @@ int shall_fork_agent(void) {
return true;
}
int _fork_agent(const char *name, char * const *argv, const int except[], size_t n_except, pid_t *ret_pid) {
int _fork_agent(const char *name, char * const *argv, const int except[], size_t n_except, PidRef *ret) {
int r;
assert(!strv_isempty(argv));
/* Spawns a temporary TTY agent, making sure it goes away when we go away */
r = safe_fork_full(name,
NULL,
(int*) except, /* safe_fork_full only changes except if you pass in FORK_PACK_FDS, which we don't */
n_except,
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_RLIMIT_NOFILE_SAFE,
ret_pid);
r = pidref_safe_fork_full(
name,
/* stdio_fds= */ NULL,
(int*) except, n_except, /* safe_fork_full only changes except if you pass in FORK_PACK_FDS, which we don't */
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_RLIMIT_NOFILE_SAFE,
ret);
if (r < 0)
return r;
if (r > 0)
+2 -2
View File
@@ -62,5 +62,5 @@ ExecCommandFlags exec_command_flags_from_string(const char *s);
int fexecve_or_execve(int executable_fd, const char *executable, char *const argv[], char *const envp[]);
int shall_fork_agent(void);
int _fork_agent(const char *name, char * const *argv, const int except[], size_t n_except, pid_t *ret_pid);
#define fork_agent(name, except, n_except, ret_pid, ...) _fork_agent(name, STRV_MAKE(__VA_ARGS__), except, n_except, ret_pid)
int _fork_agent(const char *name, char * const *argv, const int except[], size_t n_except, PidRef *ret);
#define fork_agent(name, except, n_except, ret, ...) _fork_agent(name, STRV_MAKE(__VA_ARGS__), except, n_except, ret)
+11 -5
View File
@@ -14,6 +14,7 @@
#include "locale-util.h"
#include "log.h"
#include "pager.h"
#include "pidref.h"
#include "process-util.h"
#include "signal-util.h"
#include "string-util.h"
@@ -288,8 +289,10 @@ void pager_close(void) {
stdout_redirected = stderr_redirected = false;
(void) kill(pager_pid, SIGCONT);
(void) wait_for_terminate(TAKE_PID(pager_pid), NULL);
pager_pid = 0;
_cleanup_(pidref_done) PidRef pidref = PIDREF_MAKE_FROM_PID(pager_pid);
(void) pidref_set_pid(&pidref, pager_pid);
(void) pidref_wait_for_terminate(&pidref, NULL);
TAKE_PID(pager_pid);
}
bool pager_have(void) {
@@ -299,7 +302,6 @@ bool pager_have(void) {
int show_man_page(const char *desc, bool null_stdio) {
const char *args[4] = { "man", NULL, NULL, NULL };
const char *e = NULL;
pid_t pid;
size_t k;
int r;
@@ -319,7 +321,11 @@ int show_man_page(const char *desc, bool null_stdio) {
} else
args[1] = desc;
r = safe_fork("(man)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|(null_stdio ? FORK_REARRANGE_STDIO : 0)|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = pidref_safe_fork(
"(man)",
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|(null_stdio ? FORK_REARRANGE_STDIO : 0)|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG|FORK_WAIT,
&pidref);
if (r < 0)
return r;
if (r == 0) {
@@ -329,5 +335,5 @@ int show_man_page(const char *desc, bool null_stdio) {
_exit(EXIT_FAILURE);
}
return wait_for_terminate_and_check(NULL, pid, 0);
return pidref_wait_for_terminate_and_check(NULL, &pidref, 0);
}
+5 -10
View File
@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <poll.h>
#include <signal.h>
#include <unistd.h>
#include "bus-util.h"
@@ -9,19 +8,19 @@
#include "fd-util.h"
#include "io-util.h"
#include "log.h"
#include "pidref.h"
#include "polkit-agent.h"
#include "process-util.h"
#include "stdio-util.h"
#if ENABLE_POLKIT
static pid_t agent_pid = 0;
static PidRef agent_pidref = PIDREF_NULL;
int polkit_agent_open(void) {
_cleanup_close_pair_ int pipe_fd[2] = EBADF_PAIR;
char notify_fd[DECIMAL_STR_MAX(int) + 1];
int r;
if (agent_pid > 0)
if (pidref_is_set(&agent_pidref))
return 0;
/* Clients that run as root don't need to activate/query polkit */
@@ -40,7 +39,7 @@ int polkit_agent_open(void) {
r = fork_agent("(polkit-agent)",
&pipe_fd[1],
1,
&agent_pid,
&agent_pidref,
POLKIT_AGENT_BINARY_PATH,
"--notify-fd", notify_fd,
"--fallback");
@@ -57,12 +56,8 @@ int polkit_agent_open(void) {
}
void polkit_agent_close(void) {
if (agent_pid <= 0)
return;
/* Inform agent that we are done */
sigterm_wait(TAKE_PID(agent_pid));
pidref_done_sigterm_wait(&agent_pidref);
}
#else
+6 -1
View File
@@ -448,7 +448,12 @@ int assert_signal_internal(int *ret_signal) {
return ASSERT_SIGNAL_FORK_CHILD;
}
r = wait_for_terminate(r, &siginfo);
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = pidref_set_pid(&pidref, r);
if (r < 0)
return r;
r = pidref_wait_for_terminate(&pidref, &siginfo);
if (r < 0)
return r;
+4 -3
View File
@@ -16,6 +16,7 @@
#include "initrd-util.h"
#include "log.h"
#include "main-func.h"
#include "pidref.h"
#include "proc-cmdline.h"
#include "process-util.h"
#include "special.h"
@@ -66,10 +67,10 @@ static int start_target(sd_bus *bus, const char *target) {
}
static int fork_wait(const char* const cmdline[]) {
pid_t pid;
int r;
r = safe_fork("(sulogin)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = pidref_safe_fork("(sulogin)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pidref);
if (r < 0)
return r;
if (r == 0) {
@@ -79,7 +80,7 @@ static int fork_wait(const char* const cmdline[]) {
_exit(EXIT_FAILURE); /* Operational error */
}
return wait_for_terminate_and_check(cmdline[0], pid, WAIT_LOG_ABNORMAL);
return pidref_wait_for_terminate_and_check(cmdline[0], &pidref, WAIT_LOG_ABNORMAL);
}
static void print_mode(const char* mode) {
+5 -3
View File
@@ -48,6 +48,7 @@
#include "parse-argument.h"
#include "parse-util.h"
#include "path-util.h"
#include "pidref.h"
#include "pretty-print.h"
#include "process-util.h"
#include "rm-rf.h"
@@ -2139,14 +2140,15 @@ static int merge(ImageClass image_class,
bool no_reload,
int noexec,
Hashmap *images) {
pid_t pid;
int r;
(void) dlopen_cryptsetup();
(void) dlopen_libblkid();
(void) dlopen_libmount();
r = safe_fork("(sd-merge)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_NEW_MOUNTNS, &pid);
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = pidref_safe_fork("(sd-merge)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_NEW_MOUNTNS, &pidref);
if (r < 0)
return log_error_errno(r, "Failed to fork off child: %m");
if (r == 0) {
@@ -2162,7 +2164,7 @@ static int merge(ImageClass image_class,
_exit(r > 0 ? EXIT_SUCCESS : 123); /* 123 means: didn't find any extensions */
}
r = wait_for_terminate_and_check("(sd-merge)", pid, WAIT_LOG_ABNORMAL);
r = pidref_wait_for_terminate_and_check("(sd-merge)", &pidref, WAIT_LOG_ABNORMAL);
if (r < 0)
return r;
if (r == 123) /* exit code 123 means: didn't do anything */
+4 -4
View File
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
@@ -9,6 +8,7 @@
#include "log.h"
#include "path-lookup.h"
#include "path-util.h"
#include "pidref.h"
#include "process-util.h"
#include "string-util.h"
#include "strv.h"
@@ -56,7 +56,6 @@ int enable_sysv_units(const char *verb, char **args) {
bool found_native = false, found_sysv;
const char *name;
unsigned c = 1;
pid_t pid;
int j;
name = args[f++];
@@ -122,7 +121,8 @@ int enable_sysv_units(const char *verb, char **args) {
if (!arg_quiet)
log_info("Executing: %s", l);
j = safe_fork("(sysv-install)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
j = pidref_safe_fork("(sysv-install)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pidref);
if (j < 0)
return j;
if (j == 0) {
@@ -132,7 +132,7 @@ int enable_sysv_units(const char *verb, char **args) {
_exit(EXIT_FAILURE);
}
j = wait_for_terminate_and_check("sysv-install", pid, WAIT_LOG_ABNORMAL);
j = pidref_wait_for_terminate_and_check("sysv-install", &pidref, WAIT_LOG_ABNORMAL);
if (j < 0)
return j;
if (streq(verb, "is-enabled")) {
+9 -7
View File
@@ -21,6 +21,7 @@
#include "gpt.h"
#include "hexdecoct.h"
#include "import-util.h"
#include "pidref.h"
#include "process-util.h"
#include "sort-util.h"
#include "stat-util.h"
@@ -274,7 +275,6 @@ static int download_manifest(
_cleanup_close_pair_ int pfd[2] = EBADF_PAIR;
_cleanup_fclose_ FILE *manifest = NULL;
size_t size = 0;
pid_t pid;
int r;
assert(url);
@@ -293,11 +293,13 @@ static int download_manifest(
log_info("%s Acquiring manifest file %s%s", glyph(GLYPH_DOWNLOAD),
suffixed_url, glyph(GLYPH_ELLIPSIS));
r = safe_fork_full("(sd-pull)",
(int[]) { -EBADF, pfd[1], STDERR_FILENO },
NULL, 0,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG,
&pid);
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = pidref_safe_fork_full(
"(sd-pull)",
(int[]) { -EBADF, pfd[1], STDERR_FILENO },
NULL, 0,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG,
&pidref);
if (r < 0)
return r;
if (r == 0) {
@@ -337,7 +339,7 @@ static int download_manifest(
manifest = safe_fclose(manifest);
r = wait_for_terminate_and_check("(sd-pull)", pid, WAIT_LOG);
r = pidref_wait_for_terminate_and_check("(sd-pull)", &pidref, WAIT_LOG);
if (r < 0)
return r;
if (r != 0)
+15 -30
View File
@@ -59,53 +59,38 @@ static void test_rename_process_now(const char *p, int ret) {
}
static void test_rename_process_one(const char *p, int ret) {
siginfo_t si;
pid_t pid;
int r;
log_info("/* %s(%s) */", __func__, p);
pid = fork();
assert_se(pid >= 0);
r = ASSERT_OK(safe_fork("(rename)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret_pid= */ NULL));
if (pid == 0) {
if (r == 0) {
/* child */
test_rename_process_now(p, ret);
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate(pid, &si) >= 0);
assert_se(si.si_code == CLD_EXITED);
assert_se(si.si_status == EXIT_SUCCESS);
}
TEST(rename_process_invalid) {
assert_se(rename_process(NULL) == -EINVAL);
assert_se(rename_process("") == -EINVAL);
ASSERT_ERROR(rename_process(NULL), EINVAL);
ASSERT_ERROR(rename_process(""), EINVAL);
}
TEST(rename_process_multi) {
pid_t pid;
int r;
pid = fork();
assert_se(pid >= 0);
r = ASSERT_OK(safe_fork("(rename)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret_pid= */ NULL));
if (pid > 0) {
siginfo_t si;
assert_se(wait_for_terminate(pid, &si) >= 0);
assert_se(si.si_code == CLD_EXITED);
assert_se(si.si_status == EXIT_SUCCESS);
return;
if (r == 0) {
/* child */
test_rename_process_now("one", 1);
test_rename_process_now("more", 0); /* longer than "one", hence truncated */
(void) setresuid(99, 99, 99); /* change uid when running privileged */
test_rename_process_now("time!", 0);
test_rename_process_now("0", 1); /* shorter than "one", should fit */
_exit(EXIT_SUCCESS);
}
/* child */
test_rename_process_now("one", 1);
test_rename_process_now("more", 0); /* longer than "one", hence truncated */
(void) setresuid(99, 99, 99); /* change uid when running privileged */
test_rename_process_now("time!", 0);
test_rename_process_now("0", 1); /* shorter than "one", should fit */
_exit(EXIT_SUCCESS);
}
TEST(rename_process) {
+3 -2
View File
@@ -7,6 +7,7 @@
#include "data-fd-util.h"
#include "fd-util.h"
#include "memfd-util.h"
#include "pidref.h"
#include "process-util.h"
#include "tests.h"
@@ -33,7 +34,7 @@ static void assert_equal_fd(int fd1, int fd2) {
TEST(copy_data_fd) {
_cleanup_close_ int fd1 = -EBADF, fd2 = -EBADF;
_cleanup_close_pair_ int sfd[2] = EBADF_PAIR;
_cleanup_(sigkill_waitp) pid_t pid = -1;
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
int r;
fd1 = open("/etc/fstab", O_RDONLY|O_CLOEXEC);
@@ -66,7 +67,7 @@ TEST(copy_data_fd) {
assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, sfd) >= 0);
r = safe_fork("(sd-pipe)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG, &pid);
r = pidref_safe_fork("(sd-pipe)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG, &pidref);
assert_se(r >= 0);
if (r == 0) {
+7 -8
View File
@@ -246,18 +246,17 @@ static bool apparmor_restrict_unprivileged_userns(void) {
}
static bool have_userns_privileges(void) {
pid_t pid;
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
int r;
if (apparmor_restrict_unprivileged_userns())
return false;
r = safe_fork("(sd-test-check-userns)",
FORK_RESET_SIGNALS |
FORK_CLOSE_ALL_FDS |
FORK_DEATHSIG_SIGKILL,
&pid);
ASSERT_OK(r);
r = ASSERT_OK(pidref_safe_fork(
"(sd-test-check-userns)",
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL,
&pidref));
if (r == 0) {
/* Keep CAP_SYS_ADMIN if we have it to ensure we give an
* accurate result to the caller. Some kernels have a
@@ -282,7 +281,7 @@ static bool have_userns_privileges(void) {
* EXIT_SUCCESS => we can use user namespaces
* EXIT_FAILURE => we can NOT use user namespaces
* 2 => some other error occurred */
r = wait_for_terminate_and_check("(sd-test-check-userns)", pid, 0);
r = pidref_wait_for_terminate_and_check("(sd-test-check-userns)", &pidref, 0);
if (!IN_SET(r, EXIT_SUCCESS, EXIT_FAILURE))
log_debug("Failed to check if user namespaces can be used, assuming not.");
+4 -3
View File
@@ -12,6 +12,7 @@
#include "memfd-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "pidref.h"
#include "process-util.h"
#include "random-util.h"
#include "rm-rf.h"
@@ -492,7 +493,6 @@ TEST(read_full_file_socket) {
union sockaddr_union sa;
const char *j, *jj;
size_t size;
pid_t pid;
int r;
ASSERT_OK(listener = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0));
@@ -513,7 +513,8 @@ TEST(read_full_file_socket) {
/* Bind the *client* socket to some randomized name, to verify that this works correctly. */
ASSERT_OK(asprintf(&clientname, "@%" PRIx64 "/test-bindname", random_u64()));
ASSERT_OK(r = safe_fork("(server)", FORK_DEATHSIG_SIGTERM|FORK_LOG, &pid));
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = ASSERT_OK(pidref_safe_fork("(server)", FORK_DEATHSIG_SIGTERM|FORK_LOG, &pidref));
if (r == 0) {
union sockaddr_union peer = {};
socklen_t peerlen = sizeof(peer);
@@ -540,7 +541,7 @@ TEST(read_full_file_socket) {
ASSERT_EQ(size, strlen(TEST_STR));
ASSERT_STREQ(data, TEST_STR);
ASSERT_OK(wait_for_terminate_and_check("(server)", pid, WAIT_LOG));
ASSERT_OK(pidref_wait_for_terminate_and_check("(server)", &pidref, WAIT_LOG));
#undef TEST_STR
}
+20 -20
View File
@@ -12,6 +12,7 @@
#include "fs-util.h"
#include "mkdir.h"
#include "path-util.h"
#include "pidref.h"
#include "process-util.h"
#include "random-util.h"
#include "rm-rf.h"
@@ -743,30 +744,29 @@ TEST(xopenat_lock_full) {
_cleanup_(rm_rf_physical_and_freep) char *t = NULL;
_cleanup_close_ int tfd = -EBADF, fd = -EBADF;
siginfo_t si;
int r;
assert_se((tfd = mkdtemp_open(NULL, 0, &t)) >= 0);
ASSERT_OK((tfd = mkdtemp_open(NULL, 0, &t)));
/* Test that we can acquire an exclusive lock on a directory in one process, remove the directory,
* and close the file descriptor and still properly create the directory and acquire the lock in
* another process. */
fd = xopenat_lock_full(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX);
assert_se(fd >= 0);
assert_se(faccessat(tfd, "abc", F_OK, 0) >= 0);
assert_se(fd_verify_directory(fd) >= 0);
assert_se(xopenat_lock_full(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
fd = ASSERT_OK(xopenat_lock_full(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX));
ASSERT_OK_ERRNO(faccessat(tfd, "abc", F_OK, 0));
ASSERT_OK(fd_verify_directory(fd));
ASSERT_ERROR(xopenat_lock_full(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX|LOCK_NB), EAGAIN);
pid_t pid = fork();
assert_se(pid >= 0);
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = ASSERT_OK(pidref_safe_fork("(lock)", FORK_DEATHSIG_SIGKILL|FORK_LOG, &pidref));
if (pid == 0) {
if (r == 0) {
safe_close(fd);
fd = xopenat_lock_full(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX);
assert_se(fd >= 0);
assert_se(faccessat(tfd, "abc", F_OK, 0) >= 0);
assert_se(fd_verify_directory(fd) >= 0);
assert_se(xopenat_lock_full(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
fd = ASSERT_OK(xopenat_lock_full(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX));
ASSERT_OK_ERRNO(faccessat(tfd, "abc", F_OK, 0));
ASSERT_OK(fd_verify_directory(fd));
ASSERT_ERROR(xopenat_lock_full(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX|LOCK_NB), EAGAIN);
_exit(EXIT_SUCCESS);
}
@@ -777,16 +777,16 @@ TEST(xopenat_lock_full) {
* for a little and assume that's enough time for the child process to get along far enough. It
* doesn't matter if it doesn't get far enough, in that case we just won't trigger the fallback logic
* in xopenat_lock_full(), but the test will still succeed. */
assert_se(usleep_safe(20 * USEC_PER_MSEC) >= 0);
ASSERT_OK(usleep_safe(20 * USEC_PER_MSEC));
assert_se(unlinkat(tfd, "abc", AT_REMOVEDIR) >= 0);
ASSERT_OK(unlinkat(tfd, "abc", AT_REMOVEDIR));
fd = safe_close(fd);
assert_se(wait_for_terminate(pid, &si) >= 0);
assert_se(si.si_code == CLD_EXITED);
ASSERT_OK(pidref_wait_for_terminate(&pidref, &si));
ASSERT_EQ(si.si_code, CLD_EXITED);
assert_se(xopenat_lock_full(tfd, "abc", 0, 0, 0755, LOCK_POSIX, LOCK_EX) == -EBADF);
assert_se(xopenat_lock_full(tfd, "def", O_DIRECTORY, 0, 0755, LOCK_POSIX, LOCK_EX) == -EBADF);
ASSERT_ERROR(xopenat_lock_full(tfd, "abc", 0, 0, 0755, LOCK_POSIX, LOCK_EX), EBADF);
ASSERT_ERROR(xopenat_lock_full(tfd, "def", O_DIRECTORY, 0, 0755, LOCK_POSIX, LOCK_EX), EBADF);
}
TEST(linkat_replace) {
+12 -19
View File
@@ -94,7 +94,7 @@ TEST(tmpdir) {
static void test_shareable_ns(unsigned long nsflag) {
_cleanup_close_pair_ int s[2] = EBADF_PAIR;
bool permission_denied = false;
pid_t pid1, pid2, pid3;
_cleanup_(pidref_done) PidRef pidref1 = PIDREF_NULL, pidref2 = PIDREF_NULL, pidref3 = PIDREF_NULL;
int r, n = 0;
siginfo_t si;
@@ -105,51 +105,48 @@ static void test_shareable_ns(unsigned long nsflag) {
ASSERT_OK_ERRNO(socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, s));
pid1 = fork();
ASSERT_OK_ERRNO(pid1);
r = ASSERT_OK(pidref_safe_fork("(share-ns-1)", FORK_LOG|FORK_DEATHSIG_SIGKILL, &pidref1));
if (pid1 == 0) {
if (r == 0) {
r = setup_shareable_ns(s, nsflag);
if (!ERRNO_IS_PRIVILEGE(r))
ASSERT_OK(r);
_exit(r >= 0 ? r : EX_NOPERM);
}
pid2 = fork();
ASSERT_OK_ERRNO(pid2);
r = ASSERT_OK(pidref_safe_fork("(share-ns-2)", FORK_LOG|FORK_DEATHSIG_SIGKILL, &pidref2));
if (pid2 == 0) {
if (r == 0) {
r = setup_shareable_ns(s, nsflag);
if (!ERRNO_IS_PRIVILEGE(r))
ASSERT_OK(r);
_exit(r >= 0 ? r : EX_NOPERM);
}
pid3 = fork();
ASSERT_OK_ERRNO(pid3);
r = ASSERT_OK(pidref_safe_fork("(share-ns-3)", FORK_LOG|FORK_DEATHSIG_SIGKILL, &pidref3));
if (pid3 == 0) {
if (r == 0) {
r = setup_shareable_ns(s, nsflag);
if (!ERRNO_IS_PRIVILEGE(r))
ASSERT_OK(r);
_exit(r >= 0 ? r : EX_NOPERM);
}
ASSERT_OK(wait_for_terminate(pid1, &si));
ASSERT_OK(pidref_wait_for_terminate(&pidref1, &si));
ASSERT_EQ(si.si_code, CLD_EXITED);
if (si.si_status == EX_NOPERM)
permission_denied = true;
else
n += si.si_status;
ASSERT_OK(wait_for_terminate(pid2, &si));
ASSERT_OK(pidref_wait_for_terminate(&pidref2, &si));
ASSERT_EQ(si.si_code, CLD_EXITED);
if (si.si_status == EX_NOPERM)
permission_denied = true;
else
n += si.si_status;
ASSERT_OK(wait_for_terminate(pid3, &si));
ASSERT_OK(pidref_wait_for_terminate(&pidref3, &si));
ASSERT_EQ(si.si_code, CLD_EXITED);
if (si.si_status == EX_NOPERM)
permission_denied = true;
@@ -203,7 +200,6 @@ TEST(protect_kernel_logs) {
.protect_kernel_logs = true,
.root_directory_fd = -EBADF,
};
pid_t pid;
int r;
if (geteuid() > 0) {
@@ -224,10 +220,9 @@ TEST(protect_kernel_logs) {
}
ASSERT_OK(r);
pid = fork();
ASSERT_OK_ERRNO(pid);
r = ASSERT_OK(safe_fork("(protect)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret_pid= */ NULL));
if (pid == 0) {
if (r == 0) {
_cleanup_close_ int fd = -EBADF;
ASSERT_OK_ERRNO(fd = open("/dev/kmsg", O_RDONLY | O_CLOEXEC));
@@ -239,8 +234,6 @@ TEST(protect_kernel_logs) {
_exit(EXIT_SUCCESS);
}
ASSERT_OK_EQ(wait_for_terminate_and_check("ns-kernellogs", pid, WAIT_LOG), EXIT_SUCCESS);
}
TEST(idmapping_supported) {
+3 -6
View File
@@ -464,7 +464,6 @@ TEST(find_executable) {
static void test_find_executable_exec_one(const char *path) {
_cleanup_free_ char *t = NULL;
_cleanup_close_ int fd = -EBADF;
pid_t pid;
int r;
r = find_executable_full(path, NULL, NULL, false, &t, &fd);
@@ -476,15 +475,13 @@ static void test_find_executable_exec_one(const char *path) {
if (path_is_absolute(path))
ASSERT_STREQ(t, path);
pid = fork();
assert_se(pid >= 0);
if (pid == 0) {
r = ASSERT_OK(safe_fork("(find-exec)", FORK_LOG|FORK_DEATHSIG_SIGKILL|FORK_WAIT, /* ret_pid= */ NULL));
if (r == 0) {
r = fexecve_or_execve(fd, t, STRV_MAKE(t, "--version"), STRV_MAKE(NULL));
log_error_errno(r, "[f]execve: %m");
_exit(EXIT_FAILURE);
}
assert_se(wait_for_terminate_and_check(t, pid, WAIT_LOG) == 0);
}
TEST(find_executable_exec) {
+215 -231
View File
@@ -263,7 +263,6 @@ TEST(pid_get_cmdline_harder) {
_cleanup_close_ int fd = -EBADF;
_cleanup_free_ char *line = NULL;
_cleanup_strv_free_ char **args = NULL;
pid_t pid;
int r;
if (geteuid() != 0) {
@@ -286,297 +285,286 @@ TEST(pid_get_cmdline_harder) {
}
#endif
pid = fork();
if (pid > 0) {
siginfo_t si;
r = ASSERT_OK(safe_fork("(cmdline)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret_pid= */ NULL));
if (r == 0) {
r = detach_mount_namespace();
if (r < 0) {
log_warning_errno(r, "detach mount namespace failed: %m");
if (!ERRNO_IS_PRIVILEGE(r))
ASSERT_OK(r);
return;
}
(void) wait_for_terminate(pid, &si);
fd = mkostemp(path, O_CLOEXEC);
ASSERT_OK_ERRNO(fd);
ASSERT_EQ(si.si_code, CLD_EXITED);
ASSERT_OK_ZERO(si.si_status);
/* Note that we don't unmount the following bind-mount at the end of the test because the kernel
* will clear up its /proc/PID/ hierarchy automatically as soon as the test stops. */
if (mount(path, "/proc/self/cmdline", "bind", MS_BIND, NULL) < 0) {
/* This happens under selinux… Abort the test in this case. */
log_warning_errno(errno, "mount(..., \"/proc/self/cmdline\", \"bind\", ...) failed: %m");
ASSERT_TRUE(IN_SET(errno, EPERM, EACCES));
return;
}
return;
}
/* Set RLIMIT_STACK to infinity to test we don't try to allocate unnecessarily large values to read
* the cmdline. */
if (setrlimit(RLIMIT_STACK, &RLIMIT_MAKE_CONST(RLIM_INFINITY)) < 0)
log_warning("Testing without RLIMIT_STACK=infinity");
ASSERT_OK_ZERO(pid);
ASSERT_OK_ERRNO(unlink(path));
r = detach_mount_namespace();
if (r < 0) {
log_warning_errno(r, "detach mount namespace failed: %m");
if (!ERRNO_IS_PRIVILEGE(r))
ASSERT_OK(r);
return;
}
ASSERT_OK_ERRNO(prctl(PR_SET_NAME, "testa"));
fd = mkostemp(path, O_CLOEXEC);
ASSERT_OK_ERRNO(fd);
ASSERT_ERROR(pid_get_cmdline(0, SIZE_MAX, 0, &line), ENOENT);
/* Note that we don't unmount the following bind-mount at the end of the test because the kernel
* will clear up its /proc/PID/ hierarchy automatically as soon as the test stops. */
if (mount(path, "/proc/self/cmdline", "bind", MS_BIND, NULL) < 0) {
/* This happens under selinux… Abort the test in this case. */
log_warning_errno(errno, "mount(..., \"/proc/self/cmdline\", \"bind\", ...) failed: %m");
ASSERT_TRUE(IN_SET(errno, EPERM, EACCES));
return;
}
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "[testa]");
line = mfree(line);
/* Set RLIMIT_STACK to infinity to test we don't try to allocate unnecessarily large values to read
* the cmdline. */
if (setrlimit(RLIMIT_STACK, &RLIMIT_MAKE_CONST(RLIM_INFINITY)) < 0)
log_warning("Testing without RLIMIT_STACK=infinity");
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_QUOTE, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "\"[testa]\""); /* quoting is enabled here */
line = mfree(line);
ASSERT_OK_ERRNO(unlink(path));
ASSERT_OK(pid_get_cmdline(0, 0, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "");
line = mfree(line);
ASSERT_OK_ERRNO(prctl(PR_SET_NAME, "testa"));
ASSERT_OK(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "…");
line = mfree(line);
ASSERT_ERROR(pid_get_cmdline(0, SIZE_MAX, 0, &line), ENOENT);
ASSERT_OK(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "[testa]");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[t…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_QUOTE, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "\"[testa]\""); /* quoting is enabled here */
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[te…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 0, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[tes…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[test…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[testa]");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[t…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[testa]");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[te…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[tes…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[test…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[testa]");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[testa]");
line = mfree(line);
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
ASSERT_TRUE(strv_equal(args, STRV_MAKE("[testa]")));
args = strv_free(args);
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
ASSERT_TRUE(strv_equal(args, STRV_MAKE("[testa]")));
args = strv_free(args);
/* Test with multiple arguments that don't require quoting */
ASSERT_OK_EQ_ERRNO(write(fd, "foo\0bar", 8), 8);
ASSERT_OK_EQ_ERRNO(write(fd, "foo\0bar", 8), 8);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, 0, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, 0, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "foo bar");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "foo bar");
line = mfree(line);
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
ASSERT_TRUE(strv_equal(args, STRV_MAKE("foo", "bar")));
args = strv_free(args);
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
ASSERT_TRUE(strv_equal(args, STRV_MAKE("foo", "bar")));
args = strv_free(args);
ASSERT_OK_EQ_ERRNO(write(fd, "quux", 4), 4);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, 0, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK_EQ_ERRNO(write(fd, "quux", 4), 4);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, 0, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "f…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "f…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "fo…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "fo…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo …");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo …");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo b…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo b…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo ba…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo ba…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 9, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar …");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 9, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar …");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar q…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar q…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar qu…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar qu…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 13, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 13, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 14, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 14, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 1000, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 1000, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
ASSERT_TRUE(strv_equal(args, STRV_MAKE("foo", "bar", "quux")));
args = strv_free(args);
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
ASSERT_TRUE(strv_equal(args, STRV_MAKE("foo", "bar", "quux")));
args = strv_free(args);
ASSERT_OK_ERRNO(ftruncate(fd, 0));
ASSERT_OK_ERRNO(prctl(PR_SET_NAME, "aaaa bbbb cccc"));
ASSERT_OK_ERRNO(ftruncate(fd, 0));
ASSERT_OK_ERRNO(prctl(PR_SET_NAME, "aaaa bbbb cccc"));
ASSERT_ERROR(pid_get_cmdline(0, SIZE_MAX, 0, &line), ENOENT);
ASSERT_ERROR(pid_get_cmdline(0, SIZE_MAX, 0, &line), ENOENT);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "[aaaa bbbb cccc]");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "[aaaa bbbb cccc]");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "[aaaa bbb…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "[aaaa bbb…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "[aaaa bbbb…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "[aaaa bbbb…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "[aaaa bbbb …");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "[aaaa bbbb …");
line = mfree(line);
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
ASSERT_TRUE(strv_equal(args, STRV_MAKE("[aaaa bbbb cccc]")));
args = strv_free(args);
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
ASSERT_TRUE(strv_equal(args, STRV_MAKE("[aaaa bbbb cccc]")));
args = strv_free(args);
/* Test with multiple arguments that do require quoting */
/* Test with multiple arguments that do require quoting */
#define CMDLINE1 "foo\0'bar'\0\"bar$\"\0x y z\0!``\0"
#define EXPECT1 "foo \"'bar'\" \"\\\"bar\\$\\\"\" \"x y z\" \"!\\`\\`\""
#define EXPECT1p "foo $'\\'bar\\'' $'\"bar$\"' $'x y z' $'!``'"
#define EXPECT1v STRV_MAKE("foo", "'bar'", "\"bar$\"", "x y z", "!``")
ASSERT_OK_ZERO_ERRNO(lseek(fd, 0, SEEK_SET));
ASSERT_OK_EQ_ERRNO(write(fd, CMDLINE1, sizeof(CMDLINE1)), (ssize_t) sizeof(CMDLINE1));
ASSERT_OK_ZERO_ERRNO(ftruncate(fd, sizeof(CMDLINE1)));
ASSERT_OK_ZERO_ERRNO(lseek(fd, 0, SEEK_SET));
ASSERT_OK_EQ_ERRNO(write(fd, CMDLINE1, sizeof(CMDLINE1)), (ssize_t) sizeof(CMDLINE1));
ASSERT_OK_ZERO_ERRNO(ftruncate(fd, sizeof(CMDLINE1)));
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line));
log_debug("got: ==%s==", line);
log_debug("exp: ==%s==", EXPECT1);
ASSERT_STREQ(line, EXPECT1);
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line));
log_debug("got: ==%s==", line);
log_debug("exp: ==%s==", EXPECT1);
ASSERT_STREQ(line, EXPECT1);
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line));
log_debug("got: ==%s==", line);
log_debug("exp: ==%s==", EXPECT1p);
ASSERT_STREQ(line, EXPECT1p);
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line));
log_debug("got: ==%s==", line);
log_debug("exp: ==%s==", EXPECT1p);
ASSERT_STREQ(line, EXPECT1p);
line = mfree(line);
ASSERT_OK(pid_get_cmdline_strv(0, 0, &args));
ASSERT_TRUE(strv_equal(args, EXPECT1v));
args = strv_free(args);
ASSERT_OK(pid_get_cmdline_strv(0, 0, &args));
ASSERT_TRUE(strv_equal(args, EXPECT1v));
args = strv_free(args);
#define CMDLINE2 "foo\0\1\2\3\0\0"
#define EXPECT2 "foo \"\\001\\002\\003\""
#define EXPECT2p "foo $'\\001\\002\\003'"
#define EXPECT2v STRV_MAKE("foo", "\1\2\3")
ASSERT_OK_ZERO_ERRNO(lseek(fd, 0, SEEK_SET));
ASSERT_OK_EQ_ERRNO(write(fd, CMDLINE2, sizeof(CMDLINE2)), (ssize_t) sizeof(CMDLINE2));
ASSERT_OK_ZERO_ERRNO(ftruncate(fd, sizeof CMDLINE2));
ASSERT_OK_ZERO_ERRNO(lseek(fd, 0, SEEK_SET));
ASSERT_OK_EQ_ERRNO(write(fd, CMDLINE2, sizeof(CMDLINE2)), (ssize_t) sizeof(CMDLINE2));
ASSERT_OK_ZERO_ERRNO(ftruncate(fd, sizeof CMDLINE2));
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line));
log_debug("got: ==%s==", line);
log_debug("exp: ==%s==", EXPECT2);
ASSERT_STREQ(line, EXPECT2);
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line));
log_debug("got: ==%s==", line);
log_debug("exp: ==%s==", EXPECT2);
ASSERT_STREQ(line, EXPECT2);
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line));
log_debug("got: ==%s==", line);
log_debug("exp: ==%s==", EXPECT2p);
ASSERT_STREQ(line, EXPECT2p);
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line));
log_debug("got: ==%s==", line);
log_debug("exp: ==%s==", EXPECT2p);
ASSERT_STREQ(line, EXPECT2p);
line = mfree(line);
ASSERT_OK(pid_get_cmdline_strv(0, 0, &args));
ASSERT_TRUE(strv_equal(args, EXPECT2v));
args = strv_free(args);
ASSERT_OK(pid_get_cmdline_strv(0, 0, &args));
ASSERT_TRUE(strv_equal(args, EXPECT2v));
args = strv_free(args);
safe_close(fd);
_exit(EXIT_SUCCESS);
safe_close(fd);
_exit(EXIT_SUCCESS);
}
}
TEST(getpid_cached) {
siginfo_t si;
pid_t a, b, c, d, e, f, child;
pid_t a, b, c, d, e, f;
int r;
a = getpid();
b = getpid_cached();
@@ -585,10 +573,9 @@ TEST(getpid_cached) {
ASSERT_EQ(a, b);
ASSERT_EQ(a, c);
child = fork();
ASSERT_OK_ERRNO(child);
r = ASSERT_OK(safe_fork("(getpid)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret_pid= */ NULL));
if (child == 0) {
if (r == 0) {
/* In child */
a = getpid();
b = getpid_cached();
@@ -606,10 +593,6 @@ TEST(getpid_cached) {
ASSERT_EQ(a, d);
ASSERT_EQ(a, e);
ASSERT_EQ(a, f);
ASSERT_OK(wait_for_terminate(child, &si));
ASSERT_EQ(si.si_status, 0);
ASSERT_EQ(si.si_code, CLD_EXITED);
}
TEST(getpid_measure) {
@@ -641,8 +624,6 @@ TEST(safe_fork) {
pid_t pid;
int r;
BLOCK_SIGNALS(SIGCHLD);
r = safe_fork("(test-child)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_REOPEN_LOG, &pid);
ASSERT_OK(r);
@@ -653,11 +634,14 @@ TEST(safe_fork) {
_exit(88);
}
ASSERT_OK(wait_for_terminate(pid, &status));
_cleanup_(pidref_done) PidRef child = PIDREF_NULL;
ASSERT_OK(pidref_set_pid(&child, pid));
ASSERT_OK(pidref_wait_for_terminate(&child, &status));
ASSERT_EQ(status.si_code, CLD_EXITED);
ASSERT_EQ(status.si_status, 88);
_cleanup_(pidref_done) PidRef child = PIDREF_NULL;
pidref_done(&child);
r = pidref_safe_fork("(test-child)", FORK_DETACH, &child);
if (r == 0) {
/* Don't freeze so this doesn't linger around forever in case something goes wrong. */
+7 -6
View File
@@ -23,6 +23,7 @@
#include "locale-util.h"
#include "log.h"
#include "main-func.h"
#include "pidref.h"
#include "proc-cmdline.h"
#include "process-util.h"
#include "stdio-util.h"
@@ -255,7 +256,6 @@ assert_cc(STRLEN(SYSTEMD_DEFAULT_KEYMAP) > 0);
static int keyboard_load_and_wait(const char *vc, Context *c, bool utf8) {
const char* args[8];
unsigned i = 0;
pid_t pid;
int r;
assert(vc);
@@ -286,7 +286,8 @@ static int keyboard_load_and_wait(const char *vc, Context *c, bool utf8) {
log_debug("Executing \"%s\"...", strnull(cmd));
}
r = safe_fork("(loadkeys)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = pidref_safe_fork("(loadkeys)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pidref);
if (r < 0)
return r;
if (r == 0) {
@@ -294,13 +295,12 @@ static int keyboard_load_and_wait(const char *vc, Context *c, bool utf8) {
_exit(EXIT_FAILURE);
}
return wait_for_terminate_and_check(KBD_LOADKEYS, pid, WAIT_LOG);
return pidref_wait_for_terminate_and_check(KBD_LOADKEYS, &pidref, WAIT_LOG);
}
static int font_load_and_wait(const char *vc, Context *c) {
const char* args[9];
unsigned i = 0;
pid_t pid;
int r;
assert(vc);
@@ -337,7 +337,8 @@ static int font_load_and_wait(const char *vc, Context *c) {
log_debug("Executing \"%s\"...", strnull(cmd));
}
r = safe_fork("(setfont)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = pidref_safe_fork("(setfont)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pidref);
if (r < 0)
return r;
if (r == 0) {
@@ -348,7 +349,7 @@ static int font_load_and_wait(const char *vc, Context *c) {
/* setfont returns EX_OSERR when ioctl(KDFONTOP/PIO_FONTX/PIO_FONTX) fails. This might mean various
* things, but in particular lack of a graphical console. Let's be generous and not treat this as an
* error. */
r = wait_for_terminate_and_check(KBD_SETFONT, pid, WAIT_LOG_ABNORMAL);
r = pidref_wait_for_terminate_and_check(KBD_SETFONT, &pidref, WAIT_LOG_ABNORMAL);
if (r == EX_OSERR)
log_notice(KBD_SETFONT " failed with a \"system error\" (EX_OSERR), ignoring.");
else if (r >= 0 && r != EXIT_SUCCESS)