diff options
author | Lennart Poettering <lennart@poettering.net> | 2025-01-13 11:04:19 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2025-01-16 11:55:21 +0100 |
commit | 6eeeef9f66d2ce17e9ee8e5f2168c00e20ffb412 (patch) | |
tree | d816ff629d7b63550cd9b4f443ce16f454f39fb4 | |
parent | pidref: various shortcuts to pidref_equal() (diff) | |
download | systemd-6eeeef9f66d2ce17e9ee8e5f2168c00e20ffb412.tar.xz systemd-6eeeef9f66d2ce17e9ee8e5f2168c00e20ffb412.zip |
process-util: introduce new FORK_FREEZE flag for safe_fork()
Often we want to fork off a process that just hangs until we kill it,
let's add a simple flag to create one of this type, and use it at
various places.
-rw-r--r-- | src/basic/namespace-util.c | 18 | ||||
-rw-r--r-- | src/basic/process-util.c | 3 | ||||
-rw-r--r-- | src/basic/process-util.h | 1 | ||||
-rw-r--r-- | src/test/test-pidref.c | 24 |
4 files changed, 14 insertions, 32 deletions
diff --git a/src/basic/namespace-util.c b/src/basic/namespace-util.c index 36ebda9ba4..6c559e4bf8 100644 --- a/src/basic/namespace-util.c +++ b/src/basic/namespace-util.c @@ -519,12 +519,10 @@ int userns_acquire_empty(void) { _cleanup_(pidref_done_sigkill_wait) PidRef pid = PIDREF_NULL; int r; - r = pidref_safe_fork("(sd-mkuserns)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL|FORK_NEW_USERNS, &pid); + r = pidref_safe_fork("(sd-mkuserns)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL|FORK_NEW_USERNS|FORK_FREEZE, &pid); if (r < 0) return r; - if (r == 0) - /* Child. We do nothing here, just freeze until somebody kills us. */ - freeze(); + assert(r > 0); return pidref_namespace_open_by_type(&pid, NAMESPACE_USER); } @@ -541,12 +539,10 @@ int userns_acquire(const char *uid_map, const char *gid_map) { * and then kills the process again. This way we have a userns fd that is not bound to any * process. We can use that for file system mounts and similar. */ - r = pidref_safe_fork("(sd-mkuserns)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL|FORK_NEW_USERNS, &pid); + r = pidref_safe_fork("(sd-mkuserns)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL|FORK_NEW_USERNS|FORK_FREEZE, &pid); if (r < 0) return r; - if (r == 0) - /* Child. We do nothing here, just freeze until somebody kills us. */ - freeze(); + assert(r > 0); xsprintf(path, "/proc/" PID_FMT "/uid_map", pid.pid); r = write_string_file(path, uid_map, WRITE_STRING_FILE_DISABLE_BUFFER); @@ -762,12 +758,10 @@ int netns_acquire(void) { /* Forks off a process in a new network namespace, acquires a network namespace fd, and then kills * the process again. This way we have a netns fd that is not bound to any process. */ - r = pidref_safe_fork("(sd-mknetns)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL|FORK_NEW_NETNS, &pid); + r = pidref_safe_fork("(sd-mknetns)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL|FORK_NEW_NETNS|FORK_FREEZE, &pid); if (r < 0) return log_debug_errno(r, "Failed to fork process into new netns: %m"); - if (r == 0) - /* Child. We do nothing here, just freeze until somebody kills us. */ - freeze(); + assert(r > 0); return pidref_namespace_open_by_type(&pid, NAMESPACE_NET); } diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 0367270724..73c1ab75ef 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -1763,6 +1763,9 @@ int safe_fork_full( } } + if (FLAGS_SET(flags, FORK_FREEZE)) + freeze(); + if (ret_pid) *ret_pid = getpid_cached(); diff --git a/src/basic/process-util.h b/src/basic/process-util.h index d4d7d87c06..4c24e00bd4 100644 --- a/src/basic/process-util.h +++ b/src/basic/process-util.h @@ -192,6 +192,7 @@ typedef enum ForkFlags { FORK_NEW_USERNS = 1 << 19, /* Run child in its own user namespace 💣 DO NOT USE IN THREADED PROGRAMS! 💣 */ FORK_NEW_NETNS = 1 << 20, /* Run child in its own network namespace 💣 DO NOT USE IN THREADED PROGRAMS! 💣 */ FORK_NEW_PIDNS = 1 << 21, /* Run child in its own PID namespace 💣 DO NOT USE IN THREADED PROGRAMS! 💣 */ + FORK_FREEZE = 1 << 22, /* Don't return in child, just call freeze() instead */ } ForkFlags; int safe_fork_full( diff --git a/src/test/test-pidref.c b/src/test/test-pidref.c index 5535e98ab0..10033b5826 100644 --- a/src/test/test-pidref.c +++ b/src/test/test-pidref.c @@ -159,12 +159,8 @@ TEST(pidref_new_from_pid) { TEST(pidref_kill) { _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; siginfo_t si; - int r; - r = pidref_safe_fork("(test-pidref-kill)", FORK_DEATHSIG_SIGKILL, &pidref); - assert_se(r >= 0); - if (r == 0) - freeze(); + ASSERT_OK_POSITIVE(pidref_safe_fork("(test-pidref-kill)", FORK_DEATHSIG_SIGKILL|FORK_FREEZE, &pidref)); assert_se(pidref_kill(&pidref, SIGKILL) >= 0); assert_se(pidref_wait_for_terminate(&pidref, &si) >= 0); @@ -174,12 +170,8 @@ TEST(pidref_kill) { TEST(pidref_kill_and_sigcont) { _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; siginfo_t si; - int r; - r = pidref_safe_fork("(test-pidref-kill-and-sigcont)", FORK_DEATHSIG_SIGTERM, &pidref); - assert_se(r >= 0); - if (r == 0) - freeze(); + ASSERT_OK_POSITIVE(pidref_safe_fork("(test-pidref-kill-and-sigcont)", FORK_DEATHSIG_SIGTERM|FORK_FREEZE, &pidref)); assert_se(pidref_kill_and_sigcont(&pidref, SIGTERM) >= 0); assert_se(pidref_wait_for_terminate(&pidref, &si) >= 0); @@ -189,12 +181,8 @@ TEST(pidref_kill_and_sigcont) { TEST(pidref_sigqueue) { _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; siginfo_t si; - int r; - r = pidref_safe_fork("(test-pidref-sigqueue)", FORK_DEATHSIG_SIGTERM, &pidref); - assert_se(r >= 0); - if (r == 0) - freeze(); + ASSERT_OK_POSITIVE(pidref_safe_fork("(test-pidref-sigqueue)", FORK_DEATHSIG_SIGTERM|FORK_FREEZE, &pidref)); assert_se(pidref_sigqueue(&pidref, SIGTERM, 42) >= 0); assert_se(pidref_wait_for_terminate(&pidref, &si) >= 0); @@ -203,12 +191,8 @@ TEST(pidref_sigqueue) { TEST(pidref_done_sigkill_wait) { _cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL; - int r; - r = pidref_safe_fork("(test-pidref-done-sigkill-wait)", FORK_DEATHSIG_SIGKILL, &pidref); - assert_se(r >= 0); - if (r == 0) - freeze(); + ASSERT_OK_POSITIVE(pidref_safe_fork("(test-pidref-done-sigkill-wait)", FORK_DEATHSIG_SIGKILL|FORK_FREEZE, &pidref)); } TEST(pidref_verify) { |