]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
process-util: introduce new FORK_FREEZE flag for safe_fork()
authorLennart Poettering <lennart@poettering.net>
Mon, 13 Jan 2025 10:04:19 +0000 (11:04 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 16 Jan 2025 10:55:21 +0000 (11:55 +0100)
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.

src/basic/namespace-util.c
src/basic/process-util.c
src/basic/process-util.h
src/test/test-pidref.c

index 36ebda9ba47dea22aa5fe810b939a01ee98dbdc9..6c559e4bf882d7ff543449a3aa52faacae3e532b 100644 (file)
@@ -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);
 }
index 0367270724b6ebaf537c26a95167261398c03ad3..73c1ab75ef5239de9d18033aa57afad656dc9e30 100644 (file)
@@ -1763,6 +1763,9 @@ int safe_fork_full(
                 }
         }
 
+        if (FLAGS_SET(flags, FORK_FREEZE))
+                freeze();
+
         if (ret_pid)
                 *ret_pid = getpid_cached();
 
index d4d7d87c06911b77c3f9503c6ed5516b075ab526..4c24e00bd46630ec4210bf44fcca93e832f383d9 100644 (file)
@@ -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(
index 5535e98ab07b424b35ba825e0d5707ca2cf7973d..10033b5826a03f80268937f26bf5843f7db212f7 100644 (file)
@@ -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) {