summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/basic/namespace-util.c18
-rw-r--r--src/basic/process-util.c3
-rw-r--r--src/basic/process-util.h1
-rw-r--r--src/test/test-pidref.c24
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) {