diff options
-rw-r--r-- | src/basic/missing_syscall.h | 10 | ||||
-rw-r--r-- | src/basic/pidfd-util.c | 6 | ||||
-rw-r--r-- | src/basic/pidref.c | 4 | ||||
-rw-r--r-- | src/libsystemd/sd-event/sd-event.c | 75 | ||||
-rw-r--r-- | src/libsystemd/sd-event/test-event.c | 21 | ||||
-rw-r--r-- | src/login/pam_systemd.c | 2 |
6 files changed, 35 insertions, 83 deletions
diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h index 75f4b8d81e..7db3400952 100644 --- a/src/basic/missing_syscall.h +++ b/src/basic/missing_syscall.h @@ -299,12 +299,7 @@ static inline long missing_get_mempolicy(int *mode, unsigned long *nodemask, #if !HAVE_PIDFD_SEND_SIGNAL static inline int missing_pidfd_send_signal(int fd, int sig, siginfo_t *info, unsigned flags) { -# ifdef __NR_pidfd_send_signal return syscall(__NR_pidfd_send_signal, fd, sig, info, flags); -# else - errno = ENOSYS; - return -1; -# endif } # define pidfd_send_signal missing_pidfd_send_signal @@ -312,12 +307,7 @@ static inline int missing_pidfd_send_signal(int fd, int sig, siginfo_t *info, un #if !HAVE_PIDFD_OPEN static inline int missing_pidfd_open(pid_t pid, unsigned flags) { -# ifdef __NR_pidfd_open return syscall(__NR_pidfd_open, pid, flags); -# else - errno = ENOSYS; - return -1; -# endif } # define pidfd_open missing_pidfd_open diff --git a/src/basic/pidfd-util.c b/src/basic/pidfd-util.c index 204439e444..c90699d066 100644 --- a/src/basic/pidfd-util.c +++ b/src/basic/pidfd-util.c @@ -24,12 +24,8 @@ static int pidfd_check_pidfs(void) { return have_pidfs; _cleanup_close_ int fd = pidfd_open(getpid_cached(), 0); - if (fd < 0) { - if (ERRNO_IS_NOT_SUPPORTED(errno)) - return (have_pidfs = false); - + if (fd < 0) return -errno; - } return (have_pidfs = fd_is_fs_type(fd, PID_FS_MAGIC)); } diff --git a/src/basic/pidref.c b/src/basic/pidref.c index bc3e96f426..a275f77b56 100644 --- a/src/basic/pidref.c +++ b/src/basic/pidref.c @@ -84,8 +84,8 @@ int pidref_set_pid(PidRef *pidref, pid_t pid) { fd = pidfd_open(pid, 0); if (fd < 0) { - /* Graceful fallback in case the kernel doesn't support pidfds or is out of fds */ - if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno) && !ERRNO_IS_RESOURCE(errno)) + /* Graceful fallback in case the kernel is out of fds */ + if (!ERRNO_IS_RESOURCE(errno)) return log_debug_errno(errno, "Failed to open pidfd for pid " PID_FMT ": %m", pid); fd = -EBADF; diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c index 563b7626fb..3d1b6fb228 100644 --- a/src/libsystemd/sd-event/sd-event.c +++ b/src/libsystemd/sd-event/sd-event.c @@ -25,6 +25,7 @@ #include "missing_magic.h" #include "missing_syscall.h" #include "missing_threads.h" +#include "missing_wait.h" #include "origin-id.h" #include "path-util.h" #include "prioq.h" @@ -1074,6 +1075,8 @@ static void source_disconnect(sd_event_source *s) { } static sd_event_source* source_free(sd_event_source *s) { + int r; + assert(s); source_disconnect(s); @@ -1087,31 +1090,23 @@ static sd_event_source* source_free(sd_event_source *s) { if (s->child.process_owned) { if (!s->child.exited) { - bool sent = false; - - if (s->child.pidfd >= 0) { - if (pidfd_send_signal(s->child.pidfd, SIGKILL, NULL, 0) < 0) { - if (errno == ESRCH) /* Already dead */ - sent = true; - else if (!ERRNO_IS_NOT_SUPPORTED(errno)) - log_debug_errno(errno, "Failed to kill process " PID_FMT " via pidfd_send_signal(), re-trying via kill(): %m", - s->child.pid); - } else - sent = true; - } - - if (!sent) - if (kill(s->child.pid, SIGKILL) < 0) - if (errno != ESRCH) /* Already dead */ - log_debug_errno(errno, "Failed to kill process " PID_FMT " via kill(), ignoring: %m", - s->child.pid); + if (s->child.pidfd >= 0) + r = RET_NERRNO(pidfd_send_signal(s->child.pidfd, SIGKILL, NULL, 0)); + else + r = RET_NERRNO(kill(s->child.pid, SIGKILL)); + if (r < 0 && r != -ESRCH) + log_debug_errno(r, "Failed to kill process " PID_FMT ", ignoring: %m", + s->child.pid); } if (!s->child.waited) { siginfo_t si = {}; /* Reap the child if we can */ - (void) waitid(P_PID, s->child.pid, &si, WEXITED); + if (s->child.pidfd >= 0) + (void) waitid(P_PIDFD, s->child.pidfd, &si, WEXITED); + else + (void) waitid(P_PID, s->child.pid, &si, WEXITED); } } @@ -1578,11 +1573,6 @@ static int child_exit_callback(sd_event_source *s, const siginfo_t *si, void *us return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata)); } -static bool shall_use_pidfd(void) { - /* Mostly relevant for debugging, i.e. this is used in test-event.c to test the event loop once with and once without pidfd */ - return secure_getenv_bool("SYSTEMD_PIDFD") != 0; -} - _public_ int sd_event_add_child( sd_event *e, sd_event_source **ret, @@ -1630,34 +1620,29 @@ _public_ int sd_event_add_child( if (!s) return -ENOMEM; + /* We always take a pidfd here if we can, even if we wait for anything else than WEXITED, so that we + * pin the PID, and make regular waitid() handling race-free. */ + + s->child.pidfd = pidfd_open(pid, 0); + if (s->child.pidfd < 0) + return -errno; + + s->child.pidfd_owned = true; /* If we allocate the pidfd we own it by default */ + s->wakeup = WAKEUP_EVENT_SOURCE; s->child.options = options; s->child.callback = callback; s->userdata = userdata; s->enabled = SD_EVENT_ONESHOT; - /* We always take a pidfd here if we can, even if we wait for anything else than WEXITED, so that we - * pin the PID, and make regular waitid() handling race-free. */ - - if (shall_use_pidfd()) { - s->child.pidfd = pidfd_open(pid, 0); - if (s->child.pidfd < 0) { - /* Propagate errors unless the syscall is not supported or blocked */ - if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno)) - return -errno; - } else - s->child.pidfd_owned = true; /* If we allocate the pidfd we own it by default */ - } else - s->child.pidfd = -EBADF; - if (EVENT_SOURCE_WATCH_PIDFD(s)) { - /* We have a pidfd and we only want to watch for exit */ + /* We only want to watch for exit */ r = source_child_pidfd_register(s, s->enabled); if (r < 0) return r; } else { - /* We have no pidfd or we shall wait for some other event than WEXITED */ + /* We shall wait for some other event than WEXITED */ r = event_make_signal_data(e, SIGCHLD, NULL); if (r < 0) return r; @@ -3239,12 +3224,10 @@ _public_ int sd_event_source_send_child_signal(sd_event_source *s, int sig, cons if (si) copy = *si; - if (pidfd_send_signal(s->child.pidfd, sig, si ? © : NULL, 0) < 0) { - /* Let's propagate the error only if the system call is not implemented or prohibited */ - if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno)) - return -errno; - } else - return 0; + if (pidfd_send_signal(s->child.pidfd, sig, si ? © : NULL, 0) < 0) + return -errno; + + return 0; } /* Flags are only supported for pidfd_send_signal(), not for rt_sigqueueinfo(), hence let's refuse diff --git a/src/libsystemd/sd-event/test-event.c b/src/libsystemd/sd-event/test-event.c index 57dee392d7..6394507994 100644 --- a/src/libsystemd/sd-event/test-event.c +++ b/src/libsystemd/sd-event/test-event.c @@ -198,7 +198,7 @@ static int post_handler(sd_event_source *s, void *userdata) { return 2; } -static void test_basic_one(bool with_pidfd) { +TEST(basic) { sd_event *e = NULL; sd_event_source *w = NULL, *x = NULL, *y = NULL, *z = NULL, *q = NULL, *t = NULL; static const char ch = 'x'; @@ -207,10 +207,6 @@ static void test_basic_one(bool with_pidfd) { uint64_t event_now; int64_t priority; - log_info("/* %s(pidfd=%s) */", __func__, yes_no(with_pidfd)); - - assert_se(setenv("SYSTEMD_PIDFD", yes_no(with_pidfd), 1) >= 0); - assert_se(pipe(a) >= 0); assert_se(pipe(b) >= 0); assert_se(pipe(d) >= 0); @@ -301,13 +297,6 @@ static void test_basic_one(bool with_pidfd) { safe_close_pair(b); safe_close_pair(d); safe_close_pair(k); - - assert_se(unsetenv("SYSTEMD_PIDFD") >= 0); -} - -TEST(basic) { - test_basic_one(true); /* test with pidfd */ - test_basic_one(false); /* test without pidfd */ } TEST(sd_event_now) { @@ -583,13 +572,7 @@ TEST(pidfd) { assert_se(pid > 1); - pidfd = pidfd_open(pid, 0); - if (pidfd < 0) { - /* No pidfd_open() supported or blocked? */ - assert_se(ERRNO_IS_NOT_SUPPORTED(errno) || ERRNO_IS_PRIVILEGE(errno)); - (void) wait_for_terminate(pid, NULL); - return; - } + ASSERT_OK(pidfd = pidfd_open(pid, 0)); pid2 = fork(); if (pid2 == 0) diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c index e0861f934c..ed08eb6cf8 100644 --- a/src/login/pam_systemd.c +++ b/src/login/pam_systemd.c @@ -876,7 +876,7 @@ static int create_session_message( if (!avoid_pidfd) { pidfd = pidfd_open(getpid_cached(), 0); - if (pidfd < 0 && !ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno)) + if (pidfd < 0) return -errno; } |