From: Lennart Poettering Date: Thu, 22 Jun 2023 09:52:06 +0000 (+0200) Subject: process-util: add helper that detects if we are a reaper process X-Git-Tag: v254-rc1~133^2~13 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=09f9530bafeebd1648bace80384b035322265c44;p=thirdparty%2Fsystemd.git process-util: add helper that detects if we are a reaper process --- diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 0f642fdf1bb..6373909bc77 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -1623,6 +1623,21 @@ int get_process_threads(pid_t pid) { return n; } +int is_reaper_process(void) { + int b = 0; + + /* Checks if we are running in a reaper process, i.e. if we are expected to deal with processes + * reparented to us. This simply checks if we are PID 1 or if PR_SET_CHILD_SUBREAPER was called. */ + + if (getpid_cached() == 1) + return true; + + if (prctl(PR_GET_CHILD_SUBREAPER, (unsigned long) &b, 0UL, 0UL, 0UL) < 0) + return -errno; + + return b != 0; +} + static const char *const sigchld_code_table[] = { [CLD_EXITED] = "exited", [CLD_KILLED] = "killed", diff --git a/src/basic/process-util.h b/src/basic/process-util.h index 230a0edb093..6ad4316614d 100644 --- a/src/basic/process-util.h +++ b/src/basic/process-util.h @@ -199,3 +199,5 @@ int setpriority_closest(int priority); _noreturn_ void freeze(void); int get_process_threads(pid_t pid); + +int is_reaper_process(void); diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c index e915207e8c7..6de09c3c11f 100644 --- a/src/test/test-process-util.c +++ b/src/test/test-process-util.c @@ -891,6 +891,53 @@ TEST(get_process_threads) { } } +TEST(is_reaper_process) { + int r; + + r = safe_fork("(regular)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_WAIT, NULL); + assert_se(r >= 0); + if (r == 0) { + /* child */ + + assert_se(is_reaper_process() == 0); + _exit(EXIT_SUCCESS); + } + + r = safe_fork("(newpid)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_WAIT, NULL); + assert_se(r >= 0); + if (r == 0) { + /* child */ + + if (unshare(CLONE_NEWPID) < 0) { + if (ERRNO_IS_PRIVILEGE(errno) || ERRNO_IS_NOT_SUPPORTED(errno)) { + log_notice("Skipping CLONE_NEWPID reaper check, lacking privileges/support"); + _exit(EXIT_SUCCESS); + } + } + + r = safe_fork("(newpid1)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_WAIT, NULL); + assert_se(r >= 0); + if (r == 0) { + /* grandchild, which is PID1 in a pidns */ + assert_se(getpid_cached() == 1); + assert_se(is_reaper_process() > 0); + _exit(EXIT_SUCCESS); + } + + _exit(EXIT_SUCCESS); + } + + r = safe_fork("(subreaper)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_WAIT, NULL); + assert_se(r >= 0); + if (r == 0) { + /* child */ + assert_se(prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0) >= 0); + + assert_se(is_reaper_process() > 0); + _exit(EXIT_SUCCESS); + } +} + static int intro(void) { log_show_color(true); return EXIT_SUCCESS;