diff --git a/TODO b/TODO index 75b25fcfce..89583ebbe7 100644 --- a/TODO +++ b/TODO @@ -241,14 +241,14 @@ Features: a local key to it. * PidRef conversion work: - - pid_is_unwaited() → pidref_is_unwaited() - - pid_is_alive() → pidref_is_alive() - - is_kernel_thread() → pidref_is_kernel_thread() - - pid_is_my_child() → pidref_is_my_child() - - get_process_uid() → pidref_get_uid() + - cg_pid_get_xyz() + - pid_from_same_root_fs() + - get_ctty_devnr() + - mount_image_in_namespace() + - bind_mount_in_namespace() + - pid1: sd_notify() receiver should use SCM_PIDFD to authenticate client - actually wait for POLLIN on pidref's pidfd in service logic - - exec_spawn() - - cg_pid_get_unit() + - exec_spawn() + safe_fork() - openpt_allocate_in_namespace() - sd_bus_creds - unit_attach_pid_to_cgroup_via_bus() diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index f4012f1c61..5caf85f443 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -291,7 +291,6 @@ static int cg_kill_items( _cleanup_set_free_ Set *allocated_set = NULL; bool done = false; int r, ret = 0, ret_log_kill = 0; - pid_t my_pid; assert(sig >= 0); @@ -310,11 +309,8 @@ static int cg_kill_items( return -ENOMEM; } - my_pid = getpid_cached(); - do { _cleanup_fclose_ FILE *f = NULL; - pid_t pid = 0; done = true; r = cg_enumerate_items(SYSTEMD_CGROUP_CONTROLLER, path, &f, item); @@ -325,25 +321,32 @@ static int cg_kill_items( return ret; } - while ((r = cg_read_pid(f, &pid)) > 0) { + for (;;) { + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; - if ((flags & CGROUP_IGNORE_SELF) && pid == my_pid) + r = cg_read_pidref(f, &pidref); + if (r < 0) + return r; + if (r == 0) + break; + + if ((flags & CGROUP_IGNORE_SELF) && pidref_is_self(&pidref)) continue; - if (set_get(s, PID_TO_PTR(pid)) == PID_TO_PTR(pid)) + if (set_get(s, PID_TO_PTR(pidref.pid)) == PID_TO_PTR(pidref.pid)) continue; if (log_kill) - ret_log_kill = log_kill(pid, sig, userdata); + ret_log_kill = log_kill(&pidref, sig, userdata); - /* If we haven't killed this process yet, kill - * it */ - if (kill(pid, sig) < 0) { - if (ret >= 0 && errno != ESRCH) - ret = -errno; + /* If we haven't killed this process yet, kill it */ + r = pidref_kill(&pidref, sig); + if (r < 0) { + if (ret >= 0 && r != -ESRCH) + ret = r; } else { if (flags & CGROUP_SIGCONT) - (void) kill(pid, SIGCONT); + (void) pidref_kill(&pidref, SIGCONT); if (ret == 0) { if (log_kill) @@ -355,7 +358,7 @@ static int cg_kill_items( done = false; - r = set_put(s, PID_TO_PTR(pid)); + r = set_put(s, PID_TO_PTR(pidref.pid)); if (r < 0) { if (ret >= 0) return r; @@ -622,11 +625,11 @@ static int controller_is_v1_accessible(const char *root, const char *controller) return laccess(cpath, root ? W_OK : F_OK); } -int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs) { +int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **ret) { int r; assert(controller); - assert(fs); + assert(ret); if (!cg_controller_is_valid(controller)) return -EINVAL; @@ -646,7 +649,7 @@ int cg_get_path_and_check(const char *controller, const char *path, const char * return r; } - return cg_get_path(controller, path, suffix, fs); + return cg_get_path(controller, path, suffix, ret); } int cg_set_xattr(const char *path, const char *name, const void *value, size_t size, int flags) { @@ -809,7 +812,7 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **ret_path) { } } -int cg_pidref_get_path(const char *controller, PidRef *pidref, char **ret_path) { +int cg_pidref_get_path(const char *controller, const PidRef *pidref, char **ret_path) { _cleanup_free_ char *path = NULL; int r; @@ -1052,30 +1055,30 @@ int cg_split_spec(const char *spec, char **ret_controller, char **ret_path) { return 0; } -int cg_mangle_path(const char *path, char **result) { +int cg_mangle_path(const char *path, char **ret) { _cleanup_free_ char *c = NULL, *p = NULL; int r; assert(path); - assert(result); + assert(ret); /* First, check if it already is a filesystem path */ if (path_startswith(path, "/sys/fs/cgroup")) - return path_simplify_alloc(path, result); + return path_simplify_alloc(path, ret); /* Otherwise, treat it as cg spec */ r = cg_split_spec(path, &c, &p); if (r < 0) return r; - return cg_get_path(c ?: SYSTEMD_CGROUP_CONTROLLER, p ?: "/", NULL, result); + return cg_get_path(c ?: SYSTEMD_CGROUP_CONTROLLER, p ?: "/", NULL, ret); } -int cg_get_root_path(char **path) { +int cg_get_root_path(char **ret_path) { char *p, *e; int r; - assert(path); + assert(ret_path); r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &p); if (r < 0) @@ -1089,17 +1092,17 @@ int cg_get_root_path(char **path) { if (e) *e = 0; - *path = p; + *ret_path = p; return 0; } -int cg_shift_path(const char *cgroup, const char *root, const char **shifted) { +int cg_shift_path(const char *cgroup, const char *root, const char **ret_shifted) { _cleanup_free_ char *rt = NULL; char *p; int r; assert(cgroup); - assert(shifted); + assert(ret_shifted); if (!root) { /* If the root was specified let's use that, otherwise @@ -1114,20 +1117,20 @@ int cg_shift_path(const char *cgroup, const char *root, const char **shifted) { p = path_startswith(cgroup, root); if (p && p > cgroup) - *shifted = p - 1; + *ret_shifted = p - 1; else - *shifted = cgroup; + *ret_shifted = cgroup; return 0; } -int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) { +int cg_pid_get_path_shifted(pid_t pid, const char *root, char **ret_cgroup) { _cleanup_free_ char *raw = NULL; const char *c; int r; assert(pid >= 0); - assert(cgroup); + assert(ret_cgroup); r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &raw); if (r < 0) @@ -1138,7 +1141,7 @@ int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) { return r; if (c == raw) - *cgroup = TAKE_PTR(raw); + *ret_cgroup = TAKE_PTR(raw); else { char *n; @@ -1146,18 +1149,18 @@ int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) { if (!n) return -ENOMEM; - *cgroup = n; + *ret_cgroup = n; } return 0; } -int cg_path_decode_unit(const char *cgroup, char **unit) { +int cg_path_decode_unit(const char *cgroup, char **ret_unit) { char *c, *s; size_t n; assert(cgroup); - assert(unit); + assert(ret_unit); n = strcspn(cgroup, "/"); if (n < 3) @@ -1173,7 +1176,7 @@ int cg_path_decode_unit(const char *cgroup, char **unit) { if (!s) return -ENOMEM; - *unit = s; + *ret_unit = s; return 0; } @@ -1261,17 +1264,17 @@ int cg_path_get_unit_path(const char *path, char **ret) { return 0; } -int cg_pid_get_unit(pid_t pid, char **unit) { +int cg_pid_get_unit(pid_t pid, char **ret_unit) { _cleanup_free_ char *cgroup = NULL; int r; - assert(unit); + assert(ret_unit); r = cg_pid_get_path_shifted(pid, NULL, &cgroup); if (r < 0) return r; - return cg_path_get_unit(cgroup, unit); + return cg_path_get_unit(cgroup, ret_unit); } /** @@ -1381,20 +1384,20 @@ int cg_path_get_user_unit(const char *path, char **ret) { return cg_path_get_unit(t, ret); } -int cg_pid_get_user_unit(pid_t pid, char **unit) { +int cg_pid_get_user_unit(pid_t pid, char **ret_unit) { _cleanup_free_ char *cgroup = NULL; int r; - assert(unit); + assert(ret_unit); r = cg_pid_get_path_shifted(pid, NULL, &cgroup); if (r < 0) return r; - return cg_path_get_user_unit(cgroup, unit); + return cg_path_get_user_unit(cgroup, ret_unit); } -int cg_path_get_machine_name(const char *path, char **machine) { +int cg_path_get_machine_name(const char *path, char **ret_machine) { _cleanup_free_ char *u = NULL; const char *sl; int r; @@ -1404,20 +1407,20 @@ int cg_path_get_machine_name(const char *path, char **machine) { return r; sl = strjoina("/run/systemd/machines/unit:", u); - return readlink_malloc(sl, machine); + return readlink_malloc(sl, ret_machine); } -int cg_pid_get_machine_name(pid_t pid, char **machine) { +int cg_pid_get_machine_name(pid_t pid, char **ret_machine) { _cleanup_free_ char *cgroup = NULL; int r; - assert(machine); + assert(ret_machine); r = cg_pid_get_path_shifted(pid, NULL, &cgroup); if (r < 0) return r; - return cg_path_get_machine_name(cgroup, machine); + return cg_path_get_machine_name(cgroup, ret_machine); } int cg_path_get_cgroupid(const char *path, uint64_t *ret) { @@ -1436,7 +1439,7 @@ int cg_path_get_cgroupid(const char *path, uint64_t *ret) { return 0; } -int cg_path_get_session(const char *path, char **session) { +int cg_path_get_session(const char *path, char **ret_session) { _cleanup_free_ char *unit = NULL; char *start, *end; int r; @@ -1458,20 +1461,20 @@ int cg_path_get_session(const char *path, char **session) { if (!session_id_valid(start)) return -ENXIO; - if (session) { + if (ret_session) { char *rr; rr = strdup(start); if (!rr) return -ENOMEM; - *session = rr; + *ret_session = rr; } return 0; } -int cg_pid_get_session(pid_t pid, char **session) { +int cg_pid_get_session(pid_t pid, char **ret_session) { _cleanup_free_ char *cgroup = NULL; int r; @@ -1479,10 +1482,10 @@ int cg_pid_get_session(pid_t pid, char **session) { if (r < 0) return r; - return cg_path_get_session(cgroup, session); + return cg_path_get_session(cgroup, ret_session); } -int cg_path_get_owner_uid(const char *path, uid_t *uid) { +int cg_path_get_owner_uid(const char *path, uid_t *ret_uid) { _cleanup_free_ char *slice = NULL; char *start, *end; int r; @@ -1496,18 +1499,19 @@ int cg_path_get_owner_uid(const char *path, uid_t *uid) { start = startswith(slice, "user-"); if (!start) return -ENXIO; + end = endswith(start, ".slice"); if (!end) return -ENXIO; *end = 0; - if (parse_uid(start, uid) < 0) + if (parse_uid(start, ret_uid) < 0) return -ENXIO; return 0; } -int cg_pid_get_owner_uid(pid_t pid, uid_t *uid) { +int cg_pid_get_owner_uid(pid_t pid, uid_t *ret_uid) { _cleanup_free_ char *cgroup = NULL; int r; @@ -1515,14 +1519,14 @@ int cg_pid_get_owner_uid(pid_t pid, uid_t *uid) { if (r < 0) return r; - return cg_path_get_owner_uid(cgroup, uid); + return cg_path_get_owner_uid(cgroup, ret_uid); } -int cg_path_get_slice(const char *p, char **slice) { +int cg_path_get_slice(const char *p, char **ret_slice) { const char *e = NULL; assert(p); - assert(slice); + assert(ret_slice); /* Finds the right-most slice unit from the beginning, but * stops before we come to the first non-slice unit. */ @@ -1542,11 +1546,11 @@ int cg_path_get_slice(const char *p, char **slice) { if (!s) return -ENOMEM; - *slice = s; + *ret_slice = s; return 0; } - return cg_path_decode_unit(e, slice); + return cg_path_decode_unit(e, ret_slice); } e = p; @@ -1554,44 +1558,44 @@ int cg_path_get_slice(const char *p, char **slice) { } } -int cg_pid_get_slice(pid_t pid, char **slice) { +int cg_pid_get_slice(pid_t pid, char **ret_slice) { _cleanup_free_ char *cgroup = NULL; int r; - assert(slice); + assert(ret_slice); r = cg_pid_get_path_shifted(pid, NULL, &cgroup); if (r < 0) return r; - return cg_path_get_slice(cgroup, slice); + return cg_path_get_slice(cgroup, ret_slice); } -int cg_path_get_user_slice(const char *p, char **slice) { +int cg_path_get_user_slice(const char *p, char **ret_slice) { const char *t; assert(p); - assert(slice); + assert(ret_slice); t = skip_user_prefix(p); if (!t) return -ENXIO; - /* And now it looks pretty much the same as for a system - * slice, so let's just use the same parser from here on. */ - return cg_path_get_slice(t, slice); + /* And now it looks pretty much the same as for a system slice, so let's just use the same parser + * from here on. */ + return cg_path_get_slice(t, ret_slice); } -int cg_pid_get_user_slice(pid_t pid, char **slice) { +int cg_pid_get_user_slice(pid_t pid, char **ret_slice) { _cleanup_free_ char *cgroup = NULL; int r; - assert(slice); + assert(ret_slice); r = cg_pid_get_path_shifted(pid, NULL, &cgroup); if (r < 0) return r; - return cg_path_get_user_slice(cgroup, slice); + return cg_path_get_user_slice(cgroup, ret_slice); } bool cg_needs_escape(const char *p) { diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index a64bdcf7a9..1022caf23c 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -191,20 +191,20 @@ typedef enum CGroupFlags { CGROUP_REMOVE = 1 << 2, } CGroupFlags; -typedef int (*cg_kill_log_func_t)(pid_t pid, int sig, void *userdata); +typedef int (*cg_kill_log_func_t)(const PidRef *pid, int sig, void *userdata); int cg_kill(const char *path, int sig, CGroupFlags flags, Set *s, cg_kill_log_func_t kill_log, void *userdata); int cg_kill_kernel_sigkill(const char *path); int cg_kill_recursive(const char *path, int sig, CGroupFlags flags, Set *s, cg_kill_log_func_t kill_log, void *userdata); int cg_split_spec(const char *spec, char **ret_controller, char **ret_path); -int cg_mangle_path(const char *path, char **result); +int cg_mangle_path(const char *path, char **ret); -int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs); -int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs); +int cg_get_path(const char *controller, const char *path, const char *suffix, char **ret); +int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **ret); -int cg_pid_get_path(const char *controller, pid_t pid, char **path); -int cg_pidref_get_path(const char *controller, PidRef *pidref, char **path); +int cg_pid_get_path(const char *controller, pid_t pid, char **ret); +int cg_pidref_get_path(const char *controller, const PidRef *pidref, char **ret); int cg_rmdir(const char *controller, const char *path); @@ -263,27 +263,27 @@ int cg_is_empty_recursive(const char *controller, const char *path); int cg_get_root_path(char **path); int cg_path_get_cgroupid(const char *path, uint64_t *ret); -int cg_path_get_session(const char *path, char **session); -int cg_path_get_owner_uid(const char *path, uid_t *uid); -int cg_path_get_unit(const char *path, char **unit); -int cg_path_get_unit_path(const char *path, char **unit); -int cg_path_get_user_unit(const char *path, char **unit); -int cg_path_get_machine_name(const char *path, char **machine); -int cg_path_get_slice(const char *path, char **slice); -int cg_path_get_user_slice(const char *path, char **slice); +int cg_path_get_session(const char *path, char **ret_session); +int cg_path_get_owner_uid(const char *path, uid_t *ret_uid); +int cg_path_get_unit(const char *path, char **ret_unit); +int cg_path_get_unit_path(const char *path, char **ret_unit); +int cg_path_get_user_unit(const char *path, char **ret_unit); +int cg_path_get_machine_name(const char *path, char **ret_machine); +int cg_path_get_slice(const char *path, char **ret_slice); +int cg_path_get_user_slice(const char *path, char **ret_slice); -int cg_shift_path(const char *cgroup, const char *cached_root, const char **shifted); -int cg_pid_get_path_shifted(pid_t pid, const char *cached_root, char **cgroup); +int cg_shift_path(const char *cgroup, const char *cached_root, const char **ret_shifted); +int cg_pid_get_path_shifted(pid_t pid, const char *cached_root, char **ret_cgroup); -int cg_pid_get_session(pid_t pid, char **session); -int cg_pid_get_owner_uid(pid_t pid, uid_t *uid); -int cg_pid_get_unit(pid_t pid, char **unit); -int cg_pid_get_user_unit(pid_t pid, char **unit); -int cg_pid_get_machine_name(pid_t pid, char **machine); -int cg_pid_get_slice(pid_t pid, char **slice); -int cg_pid_get_user_slice(pid_t pid, char **slice); +int cg_pid_get_session(pid_t pid, char **ret_session); +int cg_pid_get_owner_uid(pid_t pid, uid_t *ret_uid); +int cg_pid_get_unit(pid_t pid, char **ret_unit); +int cg_pid_get_user_unit(pid_t pid, char **ret_unit); +int cg_pid_get_machine_name(pid_t pid, char **ret_machine); +int cg_pid_get_slice(pid_t pid, char **ret_slice); +int cg_pid_get_user_slice(pid_t pid, char **ret_slice); -int cg_path_decode_unit(const char *cgroup, char **unit); +int cg_path_decode_unit(const char *cgroup, char **ret_unit); bool cg_needs_escape(const char *p); int cg_escape(const char *p, char **ret); diff --git a/src/basic/log.c b/src/basic/log.c index 7181f3a2ad..17b9b2afe0 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -1451,7 +1451,7 @@ void log_received_signal(int level, const struct signalfd_siginfo *si) { if (pid_is_valid(si->ssi_pid)) { _cleanup_free_ char *p = NULL; - (void) get_process_comm(si->ssi_pid, &p); + (void) pid_get_comm(si->ssi_pid, &p); log_full(level, "Received SIG%s from PID %"PRIu32" (%s).", diff --git a/src/basic/pidref.c b/src/basic/pidref.c index a9fbbf2c90..aa4ca063ba 100644 --- a/src/basic/pidref.c +++ b/src/basic/pidref.c @@ -186,7 +186,7 @@ int pidref_new_from_pid(pid_t pid, PidRef **ret) { return 0; } -int pidref_kill(PidRef *pidref, int sig) { +int pidref_kill(const PidRef *pidref, int sig) { if (!pidref) return -ESRCH; @@ -200,7 +200,7 @@ int pidref_kill(PidRef *pidref, int sig) { return -ESRCH; } -int pidref_kill_and_sigcont(PidRef *pidref, int sig) { +int pidref_kill_and_sigcont(const PidRef *pidref, int sig) { int r; r = pidref_kill(pidref, sig); @@ -213,7 +213,7 @@ int pidref_kill_and_sigcont(PidRef *pidref, int sig) { return 0; } -int pidref_sigqueue(PidRef *pidref, int sig, int value) { +int pidref_sigqueue(const PidRef *pidref, int sig, int value) { if (!pidref) return -ESRCH; @@ -240,7 +240,7 @@ int pidref_sigqueue(PidRef *pidref, int sig, int value) { return -ESRCH; } -int pidref_verify(PidRef *pidref) { +int pidref_verify(const PidRef *pidref) { int r; /* This is a helper that is supposed to be called after reading information from procfs via a @@ -250,6 +250,9 @@ int pidref_verify(PidRef *pidref) { if (!pidref_is_set(pidref)) return -ESRCH; + if (pidref->pid == 1) + return 1; /* PID 1 can never go away, hence never be recycled to a different process → return 1 */ + if (pidref->fd < 0) return 0; /* If we don't have a pidfd we cannot validate it, hence we assume it's all OK → return 0 */ @@ -260,6 +263,13 @@ int pidref_verify(PidRef *pidref) { return 1; /* We have a pidfd and it still points to the PID we have, hence all is *really* OK → return 1 */ } +bool pidref_is_self(const PidRef *pidref) { + if (!pidref) + return false; + + return pidref->pid == getpid_cached(); +} + static void pidref_hash_func(const PidRef *pidref, struct siphash *state) { siphash24_compress(&pidref->pid, sizeof(pidref->pid), state); } diff --git a/src/basic/pidref.h b/src/basic/pidref.h index b0427923e9..0fdc02a54b 100644 --- a/src/basic/pidref.h +++ b/src/basic/pidref.h @@ -43,6 +43,8 @@ static inline int pidref_set_self(PidRef *pidref) { return pidref_set_pid(pidref, 0); } +bool pidref_is_self(const PidRef *pidref); + void pidref_done(PidRef *pidref); PidRef *pidref_free(PidRef *pidref); DEFINE_TRIVIAL_CLEANUP_FUNC(PidRef*, pidref_free); @@ -51,11 +53,11 @@ int pidref_dup(const PidRef *pidref, PidRef **ret); int pidref_new_from_pid(pid_t pid, PidRef **ret); -int pidref_kill(PidRef *pidref, int sig); -int pidref_kill_and_sigcont(PidRef *pidref, int sig); -int pidref_sigqueue(PidRef *pidfref, int sig, int value); +int pidref_kill(const PidRef *pidref, int sig); +int pidref_kill_and_sigcont(const PidRef *pidref, int sig); +int pidref_sigqueue(const PidRef *pidfref, int sig, int value); -int pidref_verify(PidRef *pidref); +int pidref_verify(const PidRef *pidref); #define TAKE_PIDREF(p) TAKE_GENERIC((p), PidRef, PIDREF_NULL) diff --git a/src/basic/proc-cmdline.c b/src/basic/proc-cmdline.c index 48036b959c..e64f9c85d9 100644 --- a/src/basic/proc-cmdline.c +++ b/src/basic/proc-cmdline.c @@ -128,7 +128,7 @@ int proc_cmdline(char **ret) { } if (detect_container() > 0) - return get_process_cmdline(1, SIZE_MAX, 0, ret); + return pid_get_cmdline(1, SIZE_MAX, 0, ret); else return read_full_file("/proc/cmdline", ret, NULL); } @@ -147,7 +147,7 @@ static int proc_cmdline_strv_internal(char ***ret, bool filter_pid1_args) { if (detect_container() > 0) { _cleanup_strv_free_ char **args = NULL; - r = get_process_cmdline_strv(1, /* flags = */ 0, &args); + r = pid_get_cmdline_strv(1, /* flags = */ 0, &args); if (r < 0) return r; diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 6e51528065..c5883b05d1 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -25,6 +25,7 @@ #include "alloc-util.h" #include "architecture.h" #include "argv-util.h" +#include "dirent-util.h" #include "env-file.h" #include "env-util.h" #include "errno-util.h" @@ -94,7 +95,7 @@ static int get_process_state(pid_t pid) { return (unsigned char) state; } -int get_process_comm(pid_t pid, char **ret) { +int pid_get_comm(pid_t pid, char **ret) { _cleanup_free_ char *escaped = NULL, *comm = NULL; int r; @@ -132,15 +133,35 @@ int get_process_comm(pid_t pid, char **ret) { return 0; } -static int get_process_cmdline_nulstr( +int pidref_get_comm(const PidRef *pid, char **ret) { + _cleanup_free_ char *comm = NULL; + int r; + + if (!pidref_is_set(pid)) + return -ESRCH; + + r = pid_get_comm(pid->pid, &comm); + if (r < 0) + return r; + + r = pidref_verify(pid); + if (r < 0) + return r; + + if (ret) + *ret = TAKE_PTR(comm); + return 0; +} + +static int pid_get_cmdline_nulstr( pid_t pid, size_t max_size, ProcessCmdlineFlags flags, char **ret, size_t *ret_size) { + _cleanup_free_ char *t = NULL; const char *p; - char *t; size_t k; int r; @@ -164,18 +185,17 @@ static int get_process_cmdline_nulstr( return r; if (k == 0) { - t = mfree(t); - if (!(flags & PROCESS_CMDLINE_COMM_FALLBACK)) return -ENOENT; /* Kernel threads have no argv[] */ _cleanup_free_ char *comm = NULL; - r = get_process_comm(pid, &comm); + r = pid_get_comm(pid, &comm); if (r < 0) return r; + free(t); t = strjoin("[", comm, "]"); if (!t) return -ENOMEM; @@ -186,12 +206,15 @@ static int get_process_cmdline_nulstr( t[max_size] = '\0'; } - *ret = t; - *ret_size = k; + if (ret) + *ret = TAKE_PTR(t); + if (ret_size) + *ret_size = k; + return r; } -int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **ret) { +int pid_get_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **ret) { _cleanup_free_ char *t = NULL; size_t k; char *ans; @@ -213,7 +236,7 @@ int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags * Returns -ESRCH if the process doesn't exist, and -ENOENT if the process has no command line (and * PROCESS_CMDLINE_COMM_FALLBACK is not specified). Returns 0 and sets *line otherwise. */ - int full = get_process_cmdline_nulstr(pid, max_columns, flags, &t, &k); + int full = pid_get_cmdline_nulstr(pid, max_columns, flags, &t, &k); if (full < 0) return full; @@ -256,7 +279,27 @@ int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags return 0; } -int get_process_cmdline_strv(pid_t pid, ProcessCmdlineFlags flags, char ***ret) { +int pidref_get_cmdline(const PidRef *pid, size_t max_columns, ProcessCmdlineFlags flags, char **ret) { + _cleanup_free_ char *s = NULL; + int r; + + if (!pidref_is_set(pid)) + return -ESRCH; + + r = pid_get_cmdline(pid->pid, max_columns, flags, &s); + if (r < 0) + return r; + + r = pidref_verify(pid); + if (r < 0) + return r; + + if (ret) + *ret = TAKE_PTR(s); + return 0; +} + +int pid_get_cmdline_strv(pid_t pid, ProcessCmdlineFlags flags, char ***ret) { _cleanup_free_ char *t = NULL; char **args; size_t k; @@ -266,7 +309,7 @@ int get_process_cmdline_strv(pid_t pid, ProcessCmdlineFlags flags, char ***ret) assert((flags & ~PROCESS_CMDLINE_COMM_FALLBACK) == 0); assert(ret); - r = get_process_cmdline_nulstr(pid, SIZE_MAX, flags, &t, &k); + r = pid_get_cmdline_nulstr(pid, SIZE_MAX, flags, &t, &k); if (r < 0) return r; @@ -278,6 +321,27 @@ int get_process_cmdline_strv(pid_t pid, ProcessCmdlineFlags flags, char ***ret) return 0; } +int pidref_get_cmdline_strv(const PidRef *pid, ProcessCmdlineFlags flags, char ***ret) { + _cleanup_strv_free_ char **args = NULL; + int r; + + if (!pidref_is_set(pid)) + return -ESRCH; + + r = pid_get_cmdline_strv(pid->pid, flags, &args); + if (r < 0) + return r; + + r = pidref_verify(pid); + if (r < 0) + return r; + + if (ret) + *ret = TAKE_PTR(args); + + return 0; +} + int container_get_leader(const char *machine, pid_t *pid) { _cleanup_free_ char *s = NULL, *class = NULL; const char *p; @@ -346,7 +410,7 @@ int namespace_get_leader(pid_t pid, NamespaceType type, pid_t *ret) { } } -int is_kernel_thread(pid_t pid) { +int pid_is_kernel_thread(pid_t pid) { _cleanup_free_ char *line = NULL; unsigned long long flags; size_t l, i; @@ -404,6 +468,23 @@ int is_kernel_thread(pid_t pid) { return !!(flags & PF_KTHREAD); } +int pidref_is_kernel_thread(const PidRef *pid) { + int result, r; + + if (!pidref_is_set(pid)) + return -ESRCH; + + result = pid_is_kernel_thread(pid->pid); + if (result < 0) + return result; + + r = pidref_verify(pid); /* Verify that the PID wasn't reused since */ + if (r < 0) + return r; + + return result; +} + int get_process_capeff(pid_t pid, char **ret) { const char *p; int r; @@ -492,7 +573,8 @@ static int get_process_id(pid_t pid, const char *field, uid_t *ret) { return -EIO; } -int get_process_uid(pid_t pid, uid_t *ret) { +int pid_get_uid(pid_t pid, uid_t *ret) { + assert(ret); if (pid == 0 || pid == getpid_cached()) { *ret = getuid(); @@ -502,6 +584,26 @@ int get_process_uid(pid_t pid, uid_t *ret) { return get_process_id(pid, "Uid:", ret); } +int pidref_get_uid(const PidRef *pid, uid_t *ret) { + uid_t uid; + int r; + + if (!pidref_is_set(pid)) + return -ESRCH; + + r = pid_get_uid(pid->pid, &uid); + if (r < 0) + return r; + + r = pidref_verify(pid); + if (r < 0) + return r; + + if (ret) + *ret = uid; + return 0; +} + int get_process_gid(pid_t pid, gid_t *ret) { if (pid == 0 || pid == getpid_cached()) { @@ -692,7 +794,7 @@ int wait_for_terminate_and_check(const char *name, pid_t pid, WaitFlags flags) { assert(pid > 1); if (!name) { - r = get_process_comm(pid, &buffer); + r = pid_get_comm(pid, &buffer); if (r < 0) log_debug_errno(r, "Failed to acquire process name of " PID_FMT ", ignoring: %m", pid); else @@ -914,6 +1016,9 @@ int pid_is_my_child(pid_t pid) { pid_t ppid; int r; + if (pid < 0) + return -ESRCH; + if (pid <= 1) return false; @@ -924,11 +1029,28 @@ int pid_is_my_child(pid_t pid) { return ppid == getpid_cached(); } -bool pid_is_unwaited(pid_t pid) { +int pidref_is_my_child(const PidRef *pid) { + int r, result; + + if (!pidref_is_set(pid)) + return -ESRCH; + + result = pid_is_my_child(pid->pid); + if (result < 0) + return result; + + r = pidref_verify(pid); + if (r < 0) + return r; + + return result; +} + +int pid_is_unwaited(pid_t pid) { /* Checks whether a PID is still valid at all, including a zombie */ if (pid < 0) - return false; + return -ESRCH; if (pid <= 1) /* If we or PID 1 would be dead and have been waited for, this code would not be running */ return true; @@ -942,13 +1064,31 @@ bool pid_is_unwaited(pid_t pid) { return errno != ESRCH; } -bool pid_is_alive(pid_t pid) { +int pidref_is_unwaited(const PidRef *pid) { + int r; + + if (!pidref_is_set(pid)) + return -ESRCH; + + if (pid->pid == 1 || pidref_is_self(pid)) + return true; + + r = pidref_kill(pid, 0); + if (r == -ESRCH) + return false; + if (r < 0) + return r; + + return true; +} + +int pid_is_alive(pid_t pid) { int r; /* Checks whether a PID is still valid and not a zombie */ if (pid < 0) - return false; + return -ESRCH; if (pid <= 1) /* If we or PID 1 would be a zombie, this code would not be running */ return true; @@ -957,10 +1097,31 @@ bool pid_is_alive(pid_t pid) { return true; r = get_process_state(pid); - if (IN_SET(r, -ESRCH, 'Z')) + if (r == -ESRCH) return false; + if (r < 0) + return r; - return true; + return r != 'Z'; +} + +int pidref_is_alive(const PidRef *pidref) { + int r, result; + + if (!pidref_is_set(pidref)) + return -ESRCH; + + result = pid_is_alive(pidref->pid); + if (result < 0) + return result; + + r = pidref_verify(pidref); + if (r == -ESRCH) + return false; + if (r < 0) + return r; + + return result; } int pid_from_same_root_fs(pid_t pid) { @@ -1803,6 +1964,74 @@ fail: return -r; } +int proc_dir_open(DIR **ret) { + DIR *d; + + assert(ret); + + d = opendir("/proc"); + if (!d) + return -errno; + + *ret = d; + return 0; +} + +int proc_dir_read(DIR *d, pid_t *ret) { + assert(d); + + for (;;) { + struct dirent *de; + + errno = 0; + de = readdir_no_dot(d); + if (!de) { + if (errno != 0) + return -errno; + + break; + } + + if (!IN_SET(de->d_type, DT_DIR, DT_UNKNOWN)) + continue; + + if (parse_pid(de->d_name, ret) >= 0) + return 1; + } + + if (ret) + *ret = 0; + return 0; +} + +int proc_dir_read_pidref(DIR *d, PidRef *ret) { + int r; + + assert(d); + + for (;;) { + pid_t pid; + + r = proc_dir_read(d, &pid); + if (r < 0) + return r; + if (r == 0) + break; + + r = pidref_set_pid(ret, pid); + if (r == -ESRCH) /* gone by now? skip it */ + continue; + if (r < 0) + return r; + + return 1; + } + + if (ret) + *ret = PIDREF_NULL; + return 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 7dfa510b93..a18a730936 100644 --- a/src/basic/process-util.h +++ b/src/basic/process-util.h @@ -39,11 +39,15 @@ typedef enum ProcessCmdlineFlags { PROCESS_CMDLINE_QUOTE_POSIX = 1 << 3, } ProcessCmdlineFlags; -int get_process_comm(pid_t pid, char **ret); -int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **ret); -int get_process_cmdline_strv(pid_t pid, ProcessCmdlineFlags flags, char ***ret); +int pid_get_comm(pid_t pid, char **ret); +int pidref_get_comm(const PidRef *pid, char **ret); +int pid_get_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **ret); +int pidref_get_cmdline(const PidRef *pid, size_t max_columns, ProcessCmdlineFlags flags, char **ret); +int pid_get_cmdline_strv(pid_t pid, ProcessCmdlineFlags flags, char ***ret); +int pidref_get_cmdline_strv(const PidRef *pid, ProcessCmdlineFlags flags, char ***ret); int get_process_exe(pid_t pid, char **ret); -int get_process_uid(pid_t pid, uid_t *ret); +int pid_get_uid(pid_t pid, uid_t *ret); +int pidref_get_uid(const PidRef *pid, uid_t *ret); int get_process_gid(pid_t pid, gid_t *ret); int get_process_capeff(pid_t pid, char **ret); int get_process_cwd(pid_t pid, char **ret); @@ -77,13 +81,17 @@ void sigkill_nowaitp(pid_t *pid); int kill_and_sigcont(pid_t pid, int sig); -int is_kernel_thread(pid_t pid); +int pid_is_kernel_thread(pid_t pid); +int pidref_is_kernel_thread(const PidRef *pid); int getenv_for_pid(pid_t pid, const char *field, char **_value); -bool pid_is_alive(pid_t pid); -bool pid_is_unwaited(pid_t pid); +int pid_is_alive(pid_t pid); +int pidref_is_alive(const PidRef *pidref); +int pid_is_unwaited(pid_t pid); +int pidref_is_unwaited(const PidRef *pidref); int pid_is_my_child(pid_t pid); +int pidref_is_my_child(const PidRef *pidref); int pid_from_same_root_fs(pid_t pid); bool is_main_thread(void); @@ -215,3 +223,7 @@ int is_reaper_process(void); int make_reaper_process(bool b); int posix_spawn_wrapper(const char *path, char *const *argv, char *const *envp, pid_t *ret_pid); + +int proc_dir_open(DIR **ret); +int proc_dir_read(DIR *d, pid_t *ret); +int proc_dir_read_pidref(DIR *d, PidRef *ret); diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c index a6adb8ce31..e34da7cf72 100644 --- a/src/cgtop/cgtop.c +++ b/src/cgtop/cgtop.c @@ -209,7 +209,7 @@ static int process( g->n_tasks = 0; while (cg_read_pid(f, &pid) > 0) { - if (arg_count == COUNT_USERSPACE_PROCESSES && is_kernel_thread(pid) > 0) + if (arg_count == COUNT_USERSPACE_PROCESSES && pid_is_kernel_thread(pid) > 0) continue; g->n_tasks++; diff --git a/src/core/automount.c b/src/core/automount.c index 8df715b1af..4de537fc42 100644 --- a/src/core/automount.c +++ b/src/core/automount.c @@ -991,7 +991,7 @@ static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, vo if (packet.v5_packet.pid > 0) { _cleanup_free_ char *p = NULL; - (void) get_process_comm(packet.v5_packet.pid, &p); + (void) pid_get_comm(packet.v5_packet.pid, &p); log_unit_info(UNIT(a), "Got automount request for %s, triggered by %"PRIu32" (%s)", a->where, packet.v5_packet.pid, strna(p)); } else log_unit_debug(UNIT(a), "Got direct mount request on %s", a->where); diff --git a/src/core/cgroup.c b/src/core/cgroup.c index dd46bf9237..65851ae6e8 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -3175,7 +3175,7 @@ int unit_search_main_pid(Unit *u, PidRef *ret) { if (pidref_equal(&pidref, &npidref)) /* seen already, cgroupfs reports duplicates! */ continue; - if (pid_is_my_child(npidref.pid) == 0) /* ignore processes further down the tree */ + if (pidref_is_my_child(&npidref) <= 0) /* ignore processes further down the tree */ continue; if (pidref_is_set(&pidref) != 0) @@ -3913,7 +3913,7 @@ Unit *manager_get_unit_by_pidref(Manager *m, PidRef *pid) { if (!pidref_is_set(pid)) return NULL; - if (pid->pid == getpid_cached()) + if (pidref_is_self(pid)) return hashmap_get(m->units, SPECIAL_INIT_SCOPE); if (pid->pid == 1) return NULL; diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 354fa5290b..8c9ad0ef9f 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -1232,21 +1232,21 @@ static int property_get_cgroup( return sd_bus_message_append(reply, "s", t); } -static int append_process(sd_bus_message *reply, const char *p, pid_t pid, Set *pids) { +static int append_process(sd_bus_message *reply, const char *p, PidRef *pid, Set *pids) { _cleanup_free_ char *buf = NULL, *cmdline = NULL; int r; assert(reply); - assert(pid > 0); + assert(pidref_is_set(pid)); - r = set_put(pids, PID_TO_PTR(pid)); + r = set_put(pids, PID_TO_PTR(pid->pid)); if (IN_SET(r, 0, -EEXIST)) return 0; if (r < 0) return r; if (!p) { - r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &buf); + r = cg_pidref_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &buf); if (r == -ESRCH) return 0; if (r < 0) @@ -1255,14 +1255,16 @@ static int append_process(sd_bus_message *reply, const char *p, pid_t pid, Set * p = buf; } - (void) get_process_cmdline(pid, SIZE_MAX, - PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_QUOTE, - &cmdline); + (void) pidref_get_cmdline( + pid, + SIZE_MAX, + PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_QUOTE, + &cmdline); return sd_bus_message_append(reply, "(sus)", p, - (uint32_t) pid, + (uint32_t) pid->pid, cmdline); } @@ -1281,22 +1283,28 @@ static int append_cgroup(sd_bus_message *reply, const char *p, Set *pids) { return r; for (;;) { - pid_t pid; + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; /* libvirt / qemu uses threaded mode and cgroup.procs cannot be read at the lower levels. - * From https://docs.kernel.org/admin-guide/cgroup-v2.html#threads, - * “cgroup.procs” in a threaded domain cgroup contains the PIDs of all processes in - * the subtree and is not readable in the subtree proper. */ - r = cg_read_pid(f, &pid); + * From https://docs.kernel.org/admin-guide/cgroup-v2.html#threads, “cgroup.procs” in a + * threaded domain cgroup contains the PIDs of all processes in the subtree and is not + * readable in the subtree proper. */ + + r = cg_read_pidref(f, &pidref); if (IN_SET(r, 0, -EOPNOTSUPP)) break; if (r < 0) return r; - if (is_kernel_thread(pid) > 0) + r = pidref_is_kernel_thread(&pidref); + if (r == -ESRCH) /* gone by now */ + continue; + if (r < 0) + log_debug_errno(r, "Failed to determine if " PID_FMT " is a kernel thread, assuming not: %m", pidref.pid); + if (r > 0) continue; - r = append_process(reply, p, pid, pids); + r = append_process(reply, p, &pidref, pids); if (r < 0) return r; } @@ -1361,14 +1369,14 @@ int bus_unit_method_get_processes(sd_bus_message *message, void *userdata, sd_bu /* The main and control pids might live outside of the cgroup, hence fetch them separately */ PidRef *pid = unit_main_pid(u); if (pidref_is_set(pid)) { - r = append_process(reply, NULL, pid->pid, pids); + r = append_process(reply, NULL, pid, pids); if (r < 0) return r; } pid = unit_control_pid(u); if (pidref_is_set(pid)) { - r = append_process(reply, NULL, pid->pid, pids); + r = append_process(reply, NULL, pid, pids); if (r < 0) return r; } @@ -1522,7 +1530,7 @@ int bus_unit_method_attach_processes(sd_bus_message *message, void *userdata, sd /* Let's validate security: if the sender is root, then all is OK. If the sender is any other unit, * then the process' UID and the target unit's UID have to match the sender's UID */ if (sender_uid != 0 && sender_uid != getuid()) { - r = get_process_uid(pidref->pid, &process_uid); + r = pidref_get_uid(pidref, &process_uid); if (r < 0) return sd_bus_error_set_errnof(error, r, "Failed to retrieve process UID: %m"); diff --git a/src/core/manager.c b/src/core/manager.c index 55321d1638..935e655956 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -2823,7 +2823,7 @@ static int manager_dispatch_sigchld(sd_event_source *source, void *userdata) { _cleanup_free_ char *name = NULL; Unit *u1, *u2, **array; - (void) get_process_comm(si.si_pid, &name); + (void) pid_get_comm(si.si_pid, &name); log_debug("Child "PID_FMT" (%s) died (code=%s, status=%i/%s)", si.si_pid, strna(name), diff --git a/src/core/mount.c b/src/core/mount.c index b6b76c5602..123c87ea1a 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -796,7 +796,7 @@ static int mount_coldplug(Unit *u) { return 0; if (pidref_is_set(&m->control_pid) && - pid_is_unwaited(m->control_pid.pid) && + pidref_is_unwaited(&m->control_pid) > 0 && MOUNT_STATE_WITH_PROCESS(m->deserialized_state)) { r = unit_watch_pidref(UNIT(m), &m->control_pid, /* exclusive= */ false); diff --git a/src/core/service.c b/src/core/service.c index 8846d04d23..02a35bb4ff 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -180,6 +180,8 @@ static void service_unwatch_pid_file(Service *s) { } static int service_set_main_pidref(Service *s, PidRef *pidref) { + int r; + assert(s); /* Takes ownership of the specified pidref on success, but not on failure. */ @@ -190,7 +192,7 @@ static int service_set_main_pidref(Service *s, PidRef *pidref) { if (pidref->pid <= 1) return -EINVAL; - if (pidref->pid == getpid_cached()) + if (pidref_is_self(pidref)) return -EINVAL; if (pidref_equal(&s->main_pid, pidref) && s->main_pid_known) { @@ -205,11 +207,14 @@ static int service_set_main_pidref(Service *s, PidRef *pidref) { s->main_pid = TAKE_PIDREF(*pidref); s->main_pid_known = true; - s->main_pid_alien = pid_is_my_child(s->main_pid.pid) == 0; - if (s->main_pid_alien) + r = pidref_is_my_child(&s->main_pid); + if (r < 0) + log_unit_warning_errno(UNIT(s), r, "Can't determine if process "PID_FMT" is our child, assuming it is not: %m", s->main_pid.pid); + else if (r == 0) log_unit_warning(UNIT(s), "Supervising process "PID_FMT" which is not our child. We'll most likely not notice when it exits.", s->main_pid.pid); + s->main_pid_alien = r <= 0; return 0; } @@ -1053,6 +1058,7 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) { static int service_is_suitable_main_pid(Service *s, PidRef *pid, int prio) { Unit *owner; + int r; assert(s); assert(pidref_is_set(pid)); @@ -1061,14 +1067,17 @@ static int service_is_suitable_main_pid(Service *s, PidRef *pid, int prio) { * PID is questionnable but should be accepted if the source of configuration is trusted. > 0 if the PID is * good */ - if (pid->pid == getpid_cached() || pid->pid == 1) + if (pidref_is_self(pid) || pid->pid == 1) return log_unit_full_errno(UNIT(s), prio, SYNTHETIC_ERRNO(EPERM), "New main PID "PID_FMT" is the manager, refusing.", pid->pid); if (pidref_equal(pid, &s->control_pid)) return log_unit_full_errno(UNIT(s), prio, SYNTHETIC_ERRNO(EPERM), "New main PID "PID_FMT" is the control process, refusing.", pid->pid); - if (!pid_is_alive(pid->pid)) + r = pidref_is_alive(pid); + if (r == 0) return log_unit_full_errno(UNIT(s), prio, SYNTHETIC_ERRNO(ESRCH), "New main PID "PID_FMT" does not exist or is a zombie.", pid->pid); + if (r < 0) + return log_unit_full_errno(UNIT(s), prio, r, "Failed to check if main PID "PID_FMT" exists or is a zombie.", pid->pid); owner = manager_get_unit_by_pidref(UNIT(s)->manager, pid); if (owner == UNIT(s)) { @@ -1317,7 +1326,7 @@ static int service_coldplug(Unit *u) { return r; if (pidref_is_set(&s->main_pid) && - pid_is_unwaited(s->main_pid.pid) && + pidref_is_unwaited(&s->main_pid) > 0 && (IN_SET(s->deserialized_state, SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING, @@ -1330,7 +1339,7 @@ static int service_coldplug(Unit *u) { } if (pidref_is_set(&s->control_pid) && - pid_is_unwaited(s->control_pid.pid) && + pidref_is_unwaited(&s->control_pid) > 0 && IN_SET(s->deserialized_state, SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY, @@ -1827,7 +1836,7 @@ static int main_pid_good(Service *s) { /* If it's an alien child let's check if it is still alive ... */ if (s->main_pid_alien && pidref_is_set(&s->main_pid)) - return pid_is_alive(s->main_pid.pid); + return pidref_is_alive(&s->main_pid); /* .. otherwise assume we'll get a SIGCHLD for it, which we really should wait for to collect * exit status and code */ @@ -2295,7 +2304,7 @@ static void service_kill_control_process(Service *s) { if (r < 0) { _cleanup_free_ char *comm = NULL; - (void) get_process_comm(s->control_pid.pid, &comm); + (void) pidref_get_comm(&s->control_pid, &comm); log_unit_debug_errno(UNIT(s), r, "Failed to kill control process " PID_FMT " (%s), ignoring: %m", s->control_pid.pid, strna(comm)); diff --git a/src/core/socket.c b/src/core/socket.c index dff4bc42d7..62ce29076e 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -1852,7 +1852,7 @@ static int socket_coldplug(Unit *u) { return 0; if (pidref_is_set(&s->control_pid) && - pid_is_unwaited(s->control_pid.pid) && + pidref_is_unwaited(&s->control_pid) > 0 && IN_SET(s->deserialized_state, SOCKET_START_PRE, SOCKET_START_CHOWN, diff --git a/src/core/swap.c b/src/core/swap.c index d0bce8c44b..d0aae9a534 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -557,7 +557,7 @@ static int swap_coldplug(Unit *u) { return 0; if (pidref_is_set(&s->control_pid) && - pid_is_unwaited(s->control_pid.pid) && + pidref_is_unwaited(&s->control_pid) > 0 && SWAP_STATE_WITH_PROCESS(new_state)) { r = unit_watch_pidref(UNIT(s), &s->control_pid, /* exclusive= */ false); diff --git a/src/core/unit.c b/src/core/unit.c index 4aef2e97de..a60656709a 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -2982,7 +2982,7 @@ static void unit_tidy_watch_pids(Unit *u) { if (pidref_equal(except1, e) || pidref_equal(except2, e)) continue; - if (!pid_is_unwaited(e->pid)) + if (pidref_is_unwaited(e) <= 0) unit_unwatch_pidref(u, e); } } @@ -4006,13 +4006,14 @@ static Set *unit_pid_set(pid_t main_pid, pid_t control_pid) { return TAKE_PTR(pid_set); } -static int kill_common_log(pid_t pid, int signo, void *userdata) { +static int kill_common_log(const PidRef *pid, int signo, void *userdata) { _cleanup_free_ char *comm = NULL; Unit *u = ASSERT_PTR(userdata); - (void) get_process_comm(pid, &comm); + (void) pidref_get_comm(pid, &comm); + log_unit_info(u, "Sending signal SIG%s to process " PID_FMT " (%s) on client request.", - signal_to_string(signo), pid, strna(comm)); + signal_to_string(signo), pid->pid, strna(comm)); return 1; } @@ -4081,7 +4082,7 @@ int unit_kill( if (pidref_is_set(control_pid) && IN_SET(who, KILL_CONTROL, KILL_CONTROL_FAIL, KILL_ALL, KILL_ALL_FAIL)) { _cleanup_free_ char *comm = NULL; - (void) get_process_comm(control_pid->pid, &comm); + (void) pidref_get_comm(control_pid, &comm); r = kill_or_sigqueue(control_pid, signo, code, value); if (r < 0) { @@ -4105,9 +4106,8 @@ int unit_kill( if (pidref_is_set(main_pid) && IN_SET(who, KILL_MAIN, KILL_MAIN_FAIL, KILL_ALL, KILL_ALL_FAIL)) { - _cleanup_free_ char *comm = NULL; - (void) get_process_comm(main_pid->pid, &comm); + (void) pidref_get_comm(main_pid, &comm); r = kill_or_sigqueue(main_pid, signo, code, value); if (r < 0) { @@ -4729,10 +4729,12 @@ int unit_make_transient(Unit *u) { return 0; } -static int log_kill(pid_t pid, int sig, void *userdata) { +static int log_kill(const PidRef *pid, int sig, void *userdata) { _cleanup_free_ char *comm = NULL; - (void) get_process_comm(pid, &comm); + assert(pidref_is_set(pid)); + + (void) pidref_get_comm(pid, &comm); /* Don't log about processes marked with brackets, under the assumption that these are temporary processes only, like for example systemd's own PAM stub process. */ @@ -4743,7 +4745,7 @@ static int log_kill(pid_t pid, int sig, void *userdata) { log_unit_notice(userdata, "Killing process " PID_FMT " (%s) with signal SIG%s.", - pid, + pid->pid, strna(comm), signal_to_string(sig)); @@ -4815,12 +4817,12 @@ int unit_kill_context( if (pidref_is_set(main_pid)) { if (log_func) - log_func(main_pid->pid, sig, u); + log_func(main_pid, sig, u); r = pidref_kill_and_sigcont(main_pid, sig); if (r < 0 && r != -ESRCH) { _cleanup_free_ char *comm = NULL; - (void) get_process_comm(main_pid->pid, &comm); + (void) pidref_get_comm(main_pid, &comm); log_unit_warning_errno(u, r, "Failed to kill main process " PID_FMT " (%s), ignoring: %m", main_pid->pid, strna(comm)); } else { @@ -4834,12 +4836,12 @@ int unit_kill_context( if (pidref_is_set(control_pid)) { if (log_func) - log_func(control_pid->pid, sig, u); + log_func(control_pid, sig, u); r = pidref_kill_and_sigcont(control_pid, sig); if (r < 0 && r != -ESRCH) { _cleanup_free_ char *comm = NULL; - (void) get_process_comm(control_pid->pid, &comm); + (void) pidref_get_comm(control_pid, &comm); log_unit_warning_errno(u, r, "Failed to kill control process " PID_FMT " (%s), ignoring: %m", control_pid->pid, strna(comm)); } else { @@ -5862,10 +5864,12 @@ static bool ignore_leftover_process(const char *comm) { return comm && comm[0] == '('; /* Most likely our own helper process (PAM?), ignore */ } -int unit_log_leftover_process_start(pid_t pid, int sig, void *userdata) { +int unit_log_leftover_process_start(const PidRef *pid, int sig, void *userdata) { _cleanup_free_ char *comm = NULL; - (void) get_process_comm(pid, &comm); + assert(pidref_is_set(pid)); + + (void) pidref_get_comm(pid, &comm); if (ignore_leftover_process(comm)) return 0; @@ -5875,15 +5879,17 @@ int unit_log_leftover_process_start(pid_t pid, int sig, void *userdata) { log_unit_warning(userdata, "Found left-over process " PID_FMT " (%s) in control group while starting unit. Ignoring.\n" "This usually indicates unclean termination of a previous run, or service implementation deficiencies.", - pid, strna(comm)); + pid->pid, strna(comm)); return 1; } -int unit_log_leftover_process_stop(pid_t pid, int sig, void *userdata) { +int unit_log_leftover_process_stop(const PidRef *pid, int sig, void *userdata) { _cleanup_free_ char *comm = NULL; - (void) get_process_comm(pid, &comm); + assert(pidref_is_set(pid)); + + (void) pidref_get_comm(pid, &comm); if (ignore_leftover_process(comm)) return 0; @@ -5892,7 +5898,7 @@ int unit_log_leftover_process_stop(pid_t pid, int sig, void *userdata) { log_unit_info(userdata, "Unit process " PID_FMT " (%s) remains running after unit stopped.", - pid, strna(comm)); + pid->pid, strna(comm)); return 1; } @@ -5949,11 +5955,11 @@ int unit_pid_attachable(Unit *u, PidRef *pid, sd_bus_error *error) { return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Process identifier is not valid."); /* Some extra safety check */ - if (pid->pid == 1 || pid->pid == getpid_cached()) + if (pid->pid == 1 || pidref_is_self(pid)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Process " PID_FMT " is a manager process, refusing.", pid->pid); /* Don't even begin to bother with kernel threads */ - r = is_kernel_thread(pid->pid); + r = pidref_is_kernel_thread(pid); if (r == -ESRCH) return sd_bus_error_setf(error, SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN, "Process with ID " PID_FMT " does not exist.", pid->pid); if (r < 0) diff --git a/src/core/unit.h b/src/core/unit.h index b5d7eb5f26..2427e2e765 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -1036,8 +1036,9 @@ void unit_unlink_state_files(Unit *u); int unit_prepare_exec(Unit *u); -int unit_log_leftover_process_start(pid_t pid, int sig, void *userdata); -int unit_log_leftover_process_stop(pid_t pid, int sig, void *userdata); +int unit_log_leftover_process_start(const PidRef* pid, int sig, void *userdata); +int unit_log_leftover_process_stop(const PidRef* pid, int sig, void *userdata); + int unit_warn_leftover_processes(Unit *u, cg_kill_log_func_t log_func); bool unit_needs_console(Unit *u); diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index 12f84ef965..1962512c67 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -744,7 +744,7 @@ static int get_process_container_parent_cmdline(pid_t pid, char** cmdline) { if (r < 0) return r; - r = get_process_cmdline(container_pid, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, cmdline); + r = pid_get_cmdline(container_pid, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, cmdline); if (r < 0) return r; @@ -1218,7 +1218,7 @@ static int gather_pid_metadata_from_procfs(struct iovec_wrapper *iovw, Context * pid = context->pid; /* The following is mandatory */ - r = get_process_comm(pid, &t); + r = pid_get_comm(pid, &t); if (r < 0) return log_error_errno(r, "Failed to get COMM: %m"); @@ -1251,7 +1251,7 @@ static int gather_pid_metadata_from_procfs(struct iovec_wrapper *iovw, Context * if (sd_pid_get_slice(pid, &t) >= 0) (void) iovw_put_string_field_free(iovw, "COREDUMP_SLICE=", t); - if (get_process_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &t) >= 0) + if (pid_get_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &t) >= 0) (void) iovw_put_string_field_free(iovw, "COREDUMP_CMDLINE=", t); if (cg_pid_get_path_shifted(pid, NULL, &t) >= 0) diff --git a/src/journal/journald-console.c b/src/journal/journald-console.c index 8595ba3e45..d914f92999 100644 --- a/src/journal/journald-console.c +++ b/src/journal/journald-console.c @@ -66,7 +66,7 @@ void server_forward_console( /* Second: identifier and PID */ if (ucred) { if (!identifier) { - (void) get_process_comm(ucred->pid, &ident_buf); + (void) pid_get_comm(ucred->pid, &ident_buf); identifier = ident_buf; } diff --git a/src/journal/journald-context.c b/src/journal/journald-context.c index 7274f5f3e9..cc5b4bc6ad 100644 --- a/src/journal/journald-context.c +++ b/src/journal/journald-context.c @@ -210,7 +210,7 @@ static void client_context_read_uid_gid(ClientContext *c, const struct ucred *uc if (ucred && uid_is_valid(ucred->uid)) c->uid = ucred->uid; else - (void) get_process_uid(c->pid, &c->uid); + (void) pid_get_uid(c->pid, &c->uid); if (ucred && gid_is_valid(ucred->gid)) c->gid = ucred->gid; @@ -224,13 +224,13 @@ static void client_context_read_basic(ClientContext *c) { assert(c); assert(pid_is_valid(c->pid)); - if (get_process_comm(c->pid, &t) >= 0) + if (pid_get_comm(c->pid, &t) >= 0) free_and_replace(c->comm, t); if (get_process_exe(c->pid, &t) >= 0) free_and_replace(c->exe, t); - if (get_process_cmdline(c->pid, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &t) >= 0) + if (pid_get_cmdline(c->pid, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &t) >= 0) free_and_replace(c->cmdline, t); if (get_process_capeff(c->pid, &t) >= 0) @@ -609,7 +609,7 @@ static void client_context_try_shrink_to(Server *s, size_t limit) { assert(c->n_ref == 0); - if (!pid_is_unwaited(c->pid)) + if (pid_is_unwaited(c->pid) == 0) client_context_free(s, c); else idx ++; diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c index de94dc6041..5ee4c7e057 100644 --- a/src/journal/journald-kmsg.c +++ b/src/journal/journald-kmsg.c @@ -61,7 +61,7 @@ void server_forward_kmsg( /* Second: identifier and PID */ if (ucred) { if (!identifier) { - (void) get_process_comm(ucred->pid, &ident_buf); + (void) pid_get_comm(ucred->pid, &ident_buf); identifier = ident_buf; } diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c index 1ecbd226da..c1c0a913eb 100644 --- a/src/journal/journald-syslog.c +++ b/src/journal/journald-syslog.c @@ -154,7 +154,7 @@ void server_forward_syslog(Server *s, int priority, const char *identifier, cons /* Third: identifier and PID */ if (ucred) { if (!identifier) { - (void) get_process_comm(ucred->pid, &ident_buf); + (void) pid_get_comm(ucred->pid, &ident_buf); identifier = ident_buf; } diff --git a/src/journal/journald-wall.c b/src/journal/journald-wall.c index c8d92c4d3e..79eaac1068 100644 --- a/src/journal/journald-wall.c +++ b/src/journal/journald-wall.c @@ -27,7 +27,7 @@ void server_forward_wall( if (ucred) { if (!identifier) { - (void) get_process_comm(ucred->pid, &ident_buf); + (void) pid_get_comm(ucred->pid, &ident_buf); identifier = ident_buf; } diff --git a/src/libsystemd/sd-bus/bus-creds.c b/src/libsystemd/sd-bus/bus-creds.c index d2513f1f73..c6d8caaf6d 100644 --- a/src/libsystemd/sd-bus/bus-creds.c +++ b/src/libsystemd/sd-bus/bus-creds.c @@ -139,7 +139,7 @@ sd_bus_creds* bus_creds_new(void) { } _public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t mask) { - sd_bus_creds *c; + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL; int r; assert_return(pid >= 0, -EINVAL); @@ -154,19 +154,18 @@ _public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t m return -ENOMEM; r = bus_creds_add_more(c, mask | SD_BUS_CREDS_AUGMENT, pid, 0); - if (r < 0) { - sd_bus_creds_unref(c); + if (r < 0) return r; - } /* Check if the process existed at all, in case we haven't * figured that out already */ - if (!pid_is_alive(pid)) { - sd_bus_creds_unref(c); + r = pid_is_alive(pid); + if (r < 0) + return r; + if (r == 0) return -ESRCH; - } - *ret = c; + *ret = TAKE_PTR(c); return 0; } @@ -969,7 +968,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) { } if (missing & SD_BUS_CREDS_COMM) { - r = get_process_comm(pid, &c->comm); + r = pid_get_comm(pid, &c->comm); if (r < 0) { if (!ERRNO_IS_PRIVILEGE(r)) return r; @@ -1089,15 +1088,16 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) { c->mask |= SD_BUS_CREDS_TTY; } - /* In case only the exe path was to be read we cannot - * distinguish the case where the exe path was unreadable - * because the process was a kernel thread, or when the - * process didn't exist at all. Hence, let's do a final check, - * to be sure. */ - if (!pid_is_alive(pid)) + /* In case only the exe path was to be read we cannot distinguish the case where the exe path was + * unreadable because the process was a kernel thread, or when the process didn't exist at + * all. Hence, let's do a final check, to be sure. */ + r = pid_is_alive(pid); + if (r < 0) + return r; + if (r == 0) return -ESRCH; - if (tid > 0 && tid != pid && !pid_is_unwaited(tid)) + if (tid > 0 && tid != pid && pid_is_unwaited(tid) == 0) return -ESRCH; c->augmented = missing & c->mask; diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c index cfa5633f23..5079d68550 100644 --- a/src/libsystemd/sd-bus/bus-socket.c +++ b/src/libsystemd/sd-bus/bus-socket.c @@ -920,7 +920,7 @@ static int bind_description(sd_bus *b, int fd, int family) { * - a random 64-bit value (to avoid collisions) * - our "comm" process name (suppressed if contains "/" to avoid parsing issues) * - the description string of the bus connection. */ - (void) get_process_comm(0, &comm); + (void) pid_get_comm(0, &comm); if (comm && strchr(comm, '/')) comm = mfree(comm); diff --git a/src/libsystemd/sd-bus/test-bus-peersockaddr.c b/src/libsystemd/sd-bus/test-bus-peersockaddr.c index 8bab429624..4774ef6a4c 100644 --- a/src/libsystemd/sd-bus/test-bus-peersockaddr.c +++ b/src/libsystemd/sd-bus/test-bus-peersockaddr.c @@ -47,7 +47,7 @@ static void *server(void *p) { const char *comm; assert_se(sd_bus_creds_get_comm(c, &comm) >= 0); - assert_se(get_process_comm(0, &our_comm) >= 0); + assert_se(pid_get_comm(0, &our_comm) >= 0); assert_se(streq_ptr(comm, our_comm)); const char *description; diff --git a/src/login/inhibit.c b/src/login/inhibit.c index 75dba8c08f..61fbd5df14 100644 --- a/src/login/inhibit.c +++ b/src/login/inhibit.c @@ -91,7 +91,7 @@ static int print_inhibitors(sd_bus *bus) { if (arg_mode && !streq(mode, arg_mode)) continue; - (void) get_process_comm(pid, &comm); + (void) pid_get_comm(pid, &comm); u = uid_to_name(uid); r = table_add_many(table, diff --git a/src/login/loginctl.c b/src/login/loginctl.c index 5248135d00..fdf899c37f 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -525,7 +525,7 @@ static int print_session_status_info(sd_bus *bus, const char *path) { if (i.leader > 0) { _cleanup_free_ char *name = NULL; - (void) get_process_comm(i.leader, &name); + (void) pid_get_comm(i.leader, &name); r = table_add_cell(table, NULL, TABLE_FIELD, "Leader"); if (r < 0) diff --git a/src/login/logind-action.c b/src/login/logind-action.c index 54ff795c0d..a2b211933a 100644 --- a/src/login/logind-action.c +++ b/src/login/logind-action.c @@ -239,7 +239,7 @@ int manager_handle_action( manager_is_inhibited(m, inhibit_operation, INHIBIT_BLOCK, NULL, false, false, 0, &offending)) { _cleanup_free_ char *comm = NULL, *u = NULL; - (void) get_process_comm(offending->pid.pid, &comm); + (void) pidref_get_comm(&offending->pid, &comm); u = uid_to_name(offending->uid); /* If this is just a recheck of the lid switch then don't warn about anything */ diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index ca1c485a24..b458359c97 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -1650,7 +1650,7 @@ int manager_dispatch_delayed(Manager *manager, bool timeout) { if (!timeout) return 0; - (void) get_process_comm(offending->pid.pid, &comm); + (void) pidref_get_comm(&offending->pid, &comm); u = uid_to_name(offending->uid); log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.", diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 9b6a6cebda..c9800282a5 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -526,7 +526,7 @@ static void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) { printf("\t Leader: %u", (unsigned) i->leader); - (void) get_process_comm(i->leader, &t); + (void) pid_get_comm(i->leader, &t); if (t) printf(" (%s)", t); diff --git a/src/oom/oomd-util.c b/src/oom/oomd-util.c index 99e1de182f..f9f0af2d04 100644 --- a/src/oom/oomd-util.c +++ b/src/oom/oomd-util.c @@ -26,8 +26,8 @@ DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR( OomdCGroupContext, oomd_cgroup_context_free); -static int log_kill(pid_t pid, int sig, void *userdata) { - log_debug("oomd attempting to kill " PID_FMT " with %s", pid, signal_to_string(sig)); +static int log_kill(const PidRef *pid, int sig, void *userdata) { + log_debug("oomd attempting to kill " PID_FMT " with %s", pid->pid, signal_to_string(sig)); return 0; } diff --git a/src/shared/cgroup-setup.c b/src/shared/cgroup-setup.c index fac2e08afc..811f129f6c 100644 --- a/src/shared/cgroup-setup.c +++ b/src/shared/cgroup-setup.c @@ -611,7 +611,7 @@ int cg_migrate( * them there. */ if (cfrom && empty_or_root(pfrom) && - is_kernel_thread(pid) > 0) + pid_is_kernel_thread(pid) > 0) continue; r = cg_attach(cto, pto, pid); diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c index 32e1176a57..b77bab0215 100644 --- a/src/shared/cgroup-show.c +++ b/src/shared/cgroup-show.c @@ -31,14 +31,14 @@ static void show_pid_array( pid_t pids[], - unsigned n_pids, + size_t n_pids, const char *prefix, size_t n_columns, bool extra, bool more, OutputFlags flags) { - unsigned i, j, pid_width; + size_t i, j, pid_width; if (n_pids == 0) return; @@ -65,9 +65,9 @@ static void show_pid_array( for (i = 0; i < n_pids; i++) { _cleanup_free_ char *t = NULL; - (void) get_process_cmdline(pids[i], n_columns, - PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_USE_LOCALE, - &t); + (void) pid_get_cmdline(pids[i], n_columns, + PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_USE_LOCALE, + &t); if (extra) printf("%s%s ", prefix, special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET)); @@ -114,7 +114,7 @@ static int show_cgroup_one_by_path( if (r < 0) return r; - if (!(flags & OUTPUT_KERNEL_THREADS) && is_kernel_thread(pid) > 0) + if (!(flags & OUTPUT_KERNEL_THREADS) && pid_is_kernel_thread(pid) > 0) continue; if (!GREEDY_REALLOC(pids, n + 1)) @@ -334,11 +334,11 @@ static int show_extra_pids( const char *prefix, size_t n_columns, const pid_t pids[], - unsigned n_pids, + size_t n_pids, OutputFlags flags) { _cleanup_free_ pid_t *copy = NULL; - unsigned i, j; + size_t i, j; int r; assert(path); @@ -379,7 +379,7 @@ int show_cgroup_and_extra( const char *prefix, size_t n_columns, const pid_t extra_pids[], - unsigned n_extra_pids, + size_t n_extra_pids, OutputFlags flags) { int r; diff --git a/src/shared/cgroup-show.h b/src/shared/cgroup-show.h index fbbf7663b3..db3c9c9cd0 100644 --- a/src/shared/cgroup-show.h +++ b/src/shared/cgroup-show.h @@ -12,7 +12,7 @@ int show_cgroup_by_path(const char *path, const char *prefix, size_t n_columns, OutputFlags flags); int show_cgroup(const char *controller, const char *path, const char *prefix, size_t n_columns, OutputFlags flags); -int show_cgroup_and_extra(const char *controller, const char *path, const char *prefix, size_t n_columns, const pid_t extra_pids[], unsigned n_extra_pids, OutputFlags flags); +int show_cgroup_and_extra(const char *controller, const char *path, const char *prefix, size_t n_columns, const pid_t extra_pids[], size_t n_extra_pids, OutputFlags flags); int show_cgroup_get_unit_path_and_warn( sd_bus *bus, diff --git a/src/shared/common-signal.c b/src/shared/common-signal.c index e4edd180d8..8e70e365dd 100644 --- a/src/shared/common-signal.c +++ b/src/shared/common-signal.c @@ -14,7 +14,7 @@ int sigrtmin18_handler(sd_event_source *s, const struct signalfd_siginfo *si, vo assert(s); assert(si); - (void) get_process_comm(si->ssi_pid, &comm); + (void) pid_get_comm(si->ssi_pid, &comm); if (si->ssi_code != SI_QUEUE) { log_notice("Received control signal %s from process " PID_FMT " (%s) without command value, ignoring.", diff --git a/src/shared/killall.c b/src/shared/killall.c index ef715dbdfe..9c2babe7d2 100644 --- a/src/shared/killall.c +++ b/src/shared/killall.c @@ -46,13 +46,15 @@ static bool argv_has_at(pid_t pid) { return c == '@'; } -static bool is_survivor_cgroup(pid_t pid) { +static bool is_survivor_cgroup(const PidRef *pid) { _cleanup_free_ char *cgroup_path = NULL; int r; - r = cg_pid_get_path(/* root= */ NULL, pid, &cgroup_path); + assert(pidref_is_set(pid)); + + r = cg_pidref_get_path(/* root= */ NULL, pid, &cgroup_path); if (r < 0) { - log_warning_errno(r, "Failed to get cgroup path of process " PID_FMT ", ignoring: %m", pid); + log_warning_errno(r, "Failed to get cgroup path of process " PID_FMT ", ignoring: %m", pid->pid); return false; } @@ -68,16 +70,18 @@ static bool is_survivor_cgroup(pid_t pid) { return r > 0; } -static bool ignore_proc(pid_t pid, bool warn_rootfs) { +static bool ignore_proc(const PidRef *pid, bool warn_rootfs) { uid_t uid; int r; + assert(pidref_is_set(pid)); + /* We are PID 1, let's not commit suicide */ - if (pid <= 1) + if (pid->pid == 1) return true; /* Ignore kernel threads */ - r = is_kernel_thread(pid); + r = pidref_is_kernel_thread(pid); if (r != 0) return true; /* also ignore processes where we can't determine this */ @@ -85,7 +89,7 @@ static bool ignore_proc(pid_t pid, bool warn_rootfs) { if (is_survivor_cgroup(pid)) return true; - r = get_process_uid(pid, &uid); + r = pidref_get_uid(pid, &uid); if (r < 0) return true; /* not really, but better safe than sorry */ @@ -93,20 +97,20 @@ static bool ignore_proc(pid_t pid, bool warn_rootfs) { if (uid != 0) return false; - if (!argv_has_at(pid)) + if (!argv_has_at(pid->pid)) return false; if (warn_rootfs && - pid_from_same_root_fs(pid) == 0) { + pid_from_same_root_fs(pid->pid) == 0) { _cleanup_free_ char *comm = NULL; - (void) get_process_comm(pid, &comm); + (void) pidref_get_comm(pid, &comm); log_notice("Process " PID_FMT " (%s) has been marked to be excluded from killing. It is " "running from the root file system, and thus likely to block re-mounting of the " "root file system to read-only. Please consider moving it into an initrd file " - "system instead.", pid, strna(comm)); + "system instead.", pid->pid, strna(comm)); } return true; @@ -120,12 +124,12 @@ static void log_children_no_yet_killed(Set *pids) { SET_FOREACH(p, pids) { _cleanup_free_ char *s = NULL; - if (get_process_comm(PTR_TO_PID(p), &s) >= 0) + if (pid_get_comm(PTR_TO_PID(p), &s) >= 0) r = strextendf(&lst_child, ", " PID_FMT " (%s)", PTR_TO_PID(p), s); else r = strextendf(&lst_child, ", " PID_FMT, PTR_TO_PID(p)); if (r < 0) - return (void) log_oom(); + return (void) log_oom_warning(); } if (isempty(lst_child)) @@ -223,59 +227,57 @@ static int wait_for_children(Set *pids, sigset_t *mask, usec_t timeout) { static int killall(int sig, Set *pids, bool send_sighup) { _cleanup_closedir_ DIR *dir = NULL; - int n_killed = 0; + int n_killed = 0, r; /* Send the specified signal to all remaining processes, if not excluded by ignore_proc(). * Returns the number of processes to which the specified signal was sent */ - dir = opendir("/proc"); - if (!dir) - return log_warning_errno(errno, "opendir(/proc) failed: %m"); + r = proc_dir_open(&dir); + if (r < 0) + return log_warning_errno(r, "opendir(/proc) failed: %m"); - FOREACH_DIRENT_ALL(de, dir, break) { - pid_t pid; - int r; + for (;;) { + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; - if (!IN_SET(de->d_type, DT_DIR, DT_UNKNOWN)) - continue; + r = proc_dir_read_pidref(dir, &pidref); + if (r < 0) + return log_warning_errno(r, "Failed to enumerate /proc: %m"); + if (r == 0) + break; - if (parse_pid(de->d_name, &pid) < 0) - continue; - - if (ignore_proc(pid, sig == SIGKILL && !in_initrd())) + if (ignore_proc(&pidref, sig == SIGKILL && !in_initrd())) continue; if (sig == SIGKILL) { _cleanup_free_ char *s = NULL; - (void) get_process_comm(pid, &s); - log_notice("Sending SIGKILL to PID "PID_FMT" (%s).", pid, strna(s)); + (void) pidref_get_comm(&pidref, &s); + log_notice("Sending SIGKILL to PID "PID_FMT" (%s).", pidref.pid, strna(s)); } - if (kill(pid, sig) >= 0) { + r = pidref_kill(&pidref, sig); + if (r < 0) { + if (errno != -ESRCH) + log_warning_errno(errno, "Could not kill " PID_FMT ", ignoring: %m", pidref.pid); + } else { n_killed++; if (pids) { - r = set_put(pids, PID_TO_PTR(pid)); + r = set_put(pids, PID_TO_PTR(pidref.pid)); if (r < 0) - log_oom(); + (void) log_oom_warning(); } - } else if (errno != ENOENT) - log_warning_errno(errno, "Could not kill %d: %m", pid); + } if (send_sighup) { - /* Optionally, also send a SIGHUP signal, but - only if the process has a controlling - tty. This is useful to allow handling of - shells which ignore SIGTERM but react to - SIGHUP. We do not send this to processes that - have no controlling TTY since we don't want to - trigger reloads of daemon processes. Also we - make sure to only send this after SIGTERM so - that SIGTERM is always first in the queue. */ + /* Optionally, also send a SIGHUP signal, but only if the process has a controlling + * tty. This is useful to allow handling of shells which ignore SIGTERM but react to + * SIGHUP. We do not send this to processes that have no controlling TTY since we + * don't want to trigger reloads of daemon processes. Also we make sure to only send + * this after SIGTERM so that SIGTERM is always first in the queue. */ - if (get_ctty_devnr(pid, NULL) >= 0) + if (get_ctty_devnr(pidref.pid, NULL) >= 0) /* it's OK if the process is gone, just ignore the result */ - (void) kill(pid, SIGHUP); + (void) pidref_kill(&pidref, SIGHUP); } } diff --git a/src/shutdown/umount.c b/src/shutdown/umount.c index 1586c2e214..70585523ae 100644 --- a/src/shutdown/umount.c +++ b/src/shutdown/umount.c @@ -222,7 +222,7 @@ static void log_umount_blockers(const char *mnt) { continue; _cleanup_free_ char *comm = NULL; - r = get_process_comm(pid, &comm); + r = pid_get_comm(pid, &comm); if (r < 0) { if (r != -ESRCH) /* process gone by now */ log_debug_errno(r, "Failed to read process name of PID " PID_FMT ": %m", pid); diff --git a/src/systemctl/systemctl-logind.c b/src/systemctl/systemctl-logind.c index a4486dcce9..2a697b84e5 100644 --- a/src/systemctl/systemctl-logind.c +++ b/src/systemctl/systemctl-logind.c @@ -168,7 +168,7 @@ int logind_check_inhibitors(enum action a) { ACTION_KEXEC) ? "shutdown" : "sleep")) continue; - (void) get_process_comm(pid, &comm); + (void) pid_get_comm(pid, &comm); user = uid_to_name(uid); log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".", diff --git a/src/systemctl/systemctl-show.c b/src/systemctl/systemctl-show.c index c5ed72d066..0cb75d5dfc 100644 --- a/src/systemctl/systemctl-show.c +++ b/src/systemctl/systemctl-show.c @@ -626,7 +626,7 @@ static void print_status_info( if (arg_transport == BUS_TRANSPORT_LOCAL) { _cleanup_free_ char *comm = NULL; - (void) get_process_comm(i->main_pid, &comm); + (void) pid_get_comm(i->main_pid, &comm); if (comm) printf(" (%s)", comm); } @@ -661,7 +661,7 @@ static void print_status_info( printf(PID_FMT, i->control_pid); if (arg_transport == BUS_TRANSPORT_LOCAL) { - (void) get_process_comm(i->control_pid, &c); + (void) pid_get_comm(i->control_pid, &c); if (c) printf(" (%s)", c); } diff --git a/src/test/test-argv-util.c b/src/test/test-argv-util.c index 79be836aed..5bf2903658 100644 --- a/src/test/test-argv-util.c +++ b/src/test/test-argv-util.c @@ -35,13 +35,13 @@ static void test_rename_process_now(const char *p, int ret) { return; #endif - assert_se(get_process_comm(0, &comm) >= 0); + assert_se(pid_get_comm(0, &comm) >= 0); log_debug("comm = <%s>", comm); assert_se(strneq(comm, p, TASK_COMM_LEN-1)); /* We expect comm to be at most 16 bytes (TASK_COMM_LEN). The kernel may raise this limit in the * future. We'd only check the initial part, at least until we recompile, but this will still pass. */ - r = get_process_cmdline(0, SIZE_MAX, 0, &cmdline); + r = pid_get_cmdline(0, SIZE_MAX, 0, &cmdline); assert_se(r >= 0); /* we cannot expect cmdline to be renamed properly without privileges */ if (geteuid() == 0) { diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c index afa6283011..51f52d9a4e 100644 --- a/src/test/test-cgroup-util.c +++ b/src/test/test-cgroup-util.c @@ -194,35 +194,33 @@ TEST(proc) { _cleanup_closedir_ DIR *d = NULL; int r; - d = opendir("/proc"); - assert_se(d); + assert_se(proc_dir_open(&d) >= 0); - FOREACH_DIRENT(de, d, break) { + for (;;) { _cleanup_free_ char *path = NULL, *path_shifted = NULL, *session = NULL, *unit = NULL, *user_unit = NULL, *machine = NULL, *slice = NULL; - pid_t pid; + _cleanup_(pidref_done) PidRef pid = PIDREF_NULL; uid_t uid = UID_INVALID; - if (!IN_SET(de->d_type, DT_DIR, DT_UNKNOWN)) + r = proc_dir_read_pidref(d, &pid); + assert_se(r >= 0); + + if (r == 0) + break; + + if (pidref_is_kernel_thread(&pid) != 0) continue; - r = parse_pid(de->d_name, &pid); - if (r < 0) - continue; - - if (is_kernel_thread(pid)) - continue; - - cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &path); - cg_pid_get_path_shifted(pid, NULL, &path_shifted); - cg_pid_get_owner_uid(pid, &uid); - cg_pid_get_session(pid, &session); - cg_pid_get_unit(pid, &unit); - cg_pid_get_user_unit(pid, &user_unit); - cg_pid_get_machine_name(pid, &machine); - cg_pid_get_slice(pid, &slice); + cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid.pid, &path); + cg_pid_get_path_shifted(pid.pid, NULL, &path_shifted); + cg_pid_get_owner_uid(pid.pid, &uid); + cg_pid_get_session(pid.pid, &session); + cg_pid_get_unit(pid.pid, &unit); + cg_pid_get_user_unit(pid.pid, &user_unit); + cg_pid_get_machine_name(pid.pid, &machine); + cg_pid_get_slice(pid.pid, &slice); printf(PID_FMT"\t%s\t%s\t"UID_FMT"\t%s\t%s\t%s\t%s\t%s\n", - pid, + pid.pid, path, path_shifted, uid, diff --git a/src/test/test-cgroup.c b/src/test/test-cgroup.c index c6e6b8e01a..0fbd6351a4 100644 --- a/src/test/test-cgroup.c +++ b/src/test/test-cgroup.c @@ -61,6 +61,10 @@ TEST(cg_create) { log_info("Paths for test:\n%s\n%s", test_a, test_b); + /* Possibly clean up left-overs from aboted previous runs */ + (void) cg_trim(SYSTEMD_CGROUP_CONTROLLER, test_a, /* delete_root= */ true); + (void) cg_trim(SYSTEMD_CGROUP_CONTROLLER, test_b, /* delete_root= */ true); + r = cg_create(SYSTEMD_CGROUP_CONTROLLER, test_a); if (IN_SET(r, -EPERM, -EACCES, -EROFS)) { log_info_errno(r, "Skipping %s: %m", __func__); diff --git a/src/test/test-proc-cmdline.c b/src/test/test-proc-cmdline.c index 1d13656f62..8b5bbb079e 100644 --- a/src/test/test-proc-cmdline.c +++ b/src/test/test-proc-cmdline.c @@ -274,7 +274,7 @@ TEST(proc_cmdline_key_startswith) { _cleanup_strv_free_ char **a = NULL, **b = NULL; \ const char s[] = (nulstr); \ \ - /* This emulates get_process_cmdline_strv(). */ \ + /* This emulates pid_get_cmdline_strv(). */ \ assert_se(a = strv_parse_nulstr_full(s, ELEMENTSOF(s), \ /* drop_trailing_nuls = */ true)); \ assert_se(proc_cmdline_filter_pid1_args(a, &b) >= 0); \ diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c index e3c0aa80ae..524bcceb97 100644 --- a/src/test/test-process-util.c +++ b/src/test/test-process-util.c @@ -38,7 +38,7 @@ #include "user-util.h" #include "virt.h" -static void test_get_process_comm_one(pid_t pid) { +static void test_pid_get_comm_one(pid_t pid) { struct stat st; _cleanup_free_ char *a = NULL, *c = NULL, *d = NULL, *f = NULL, *i = NULL; _cleanup_free_ char *env = NULL; @@ -54,19 +54,19 @@ static void test_get_process_comm_one(pid_t pid) { xsprintf(path, "/proc/"PID_FMT"/comm", pid); if (stat(path, &st) == 0) { - assert_se(get_process_comm(pid, &a) >= 0); + assert_se(pid_get_comm(pid, &a) >= 0); log_info("PID"PID_FMT" comm: '%s'", pid, a); } else log_warning("%s not exist.", path); - assert_se(get_process_cmdline(pid, 0, PROCESS_CMDLINE_COMM_FALLBACK, &c) >= 0); + assert_se(pid_get_cmdline(pid, 0, PROCESS_CMDLINE_COMM_FALLBACK, &c) >= 0); log_info("PID"PID_FMT" cmdline: '%s'", pid, c); - assert_se(get_process_cmdline(pid, 8, 0, &d) >= 0); + assert_se(pid_get_cmdline(pid, 8, 0, &d) >= 0); log_info("PID"PID_FMT" cmdline truncated to 8: '%s'", pid, d); free(d); - assert_se(get_process_cmdline(pid, 1, 0, &d) >= 0); + assert_se(pid_get_cmdline(pid, 1, 0, &d) >= 0); log_info("PID"PID_FMT" cmdline truncated to 1: '%s'", pid, d); r = get_process_ppid(pid, &e); @@ -76,13 +76,13 @@ static void test_get_process_comm_one(pid_t pid) { assert_se(e > 0); } - assert_se(is_kernel_thread(pid) == 0 || pid != 1); + assert_se(pid_is_kernel_thread(pid) == 0 || pid != 1); r = get_process_exe(pid, &f); assert_se(r >= 0 || r == -EACCES); log_info("PID"PID_FMT" exe: '%s'", pid, strna(f)); - assert_se(get_process_uid(pid, &u) == 0); + assert_se(pid_get_uid(pid, &u) == 0); log_info("PID"PID_FMT" UID: "UID_FMT, pid, u); assert_se(get_process_gid(pid, &g) == 0); @@ -99,100 +99,101 @@ static void test_get_process_comm_one(pid_t pid) { log_info("PID"PID_FMT" $PATH: '%s'", pid, strna(i)); } -TEST(get_process_comm) { +TEST(pid_get_comm) { if (saved_argc > 1) { pid_t pid = 0; (void) parse_pid(saved_argv[1], &pid); - test_get_process_comm_one(pid); + test_pid_get_comm_one(pid); } else { - TEST_REQ_RUNNING_SYSTEMD(test_get_process_comm_one(1)); - test_get_process_comm_one(getpid()); + TEST_REQ_RUNNING_SYSTEMD(test_pid_get_comm_one(1)); + test_pid_get_comm_one(getpid()); } } -static void test_get_process_cmdline_one(pid_t pid) { +static void test_pid_get_cmdline_one(pid_t pid) { _cleanup_free_ char *c = NULL, *d = NULL, *e = NULL, *f = NULL, *g = NULL, *h = NULL, *joined = NULL; _cleanup_strv_free_ char **strv_a = NULL, **strv_b = NULL; int r; - r = get_process_cmdline(pid, SIZE_MAX, 0, &c); + r = pid_get_cmdline(pid, SIZE_MAX, 0, &c); log_info("PID "PID_FMT": %s", pid, r >= 0 ? c : errno_to_name(r)); - r = get_process_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &d); + r = pid_get_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &d); log_info(" %s", r >= 0 ? d : errno_to_name(r)); - r = get_process_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &e); + r = pid_get_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &e); log_info(" %s", r >= 0 ? e : errno_to_name(r)); - r = get_process_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_QUOTE | PROCESS_CMDLINE_COMM_FALLBACK, &f); + r = pid_get_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_QUOTE | PROCESS_CMDLINE_COMM_FALLBACK, &f); log_info(" %s", r >= 0 ? f : errno_to_name(r)); - r = get_process_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &g); + r = pid_get_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &g); log_info(" %s", r >= 0 ? g : errno_to_name(r)); - r = get_process_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX | PROCESS_CMDLINE_COMM_FALLBACK, &h); + r = pid_get_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX | PROCESS_CMDLINE_COMM_FALLBACK, &h); log_info(" %s", r >= 0 ? h : errno_to_name(r)); - r = get_process_cmdline_strv(pid, 0, &strv_a); + r = pid_get_cmdline_strv(pid, 0, &strv_a); if (r >= 0) assert_se(joined = strv_join(strv_a, "\", \"")); log_info(" \"%s\"", r >= 0 ? joined : errno_to_name(r)); joined = mfree(joined); - r = get_process_cmdline_strv(pid, PROCESS_CMDLINE_COMM_FALLBACK, &strv_b); + r = pid_get_cmdline_strv(pid, PROCESS_CMDLINE_COMM_FALLBACK, &strv_b); if (r >= 0) assert_se(joined = strv_join(strv_b, "\", \"")); log_info(" \"%s\"", r >= 0 ? joined : errno_to_name(r)); } -TEST(get_process_cmdline) { +TEST(pid_get_cmdline) { _cleanup_closedir_ DIR *d = NULL; + int r; - assert_se(d = opendir("/proc")); + assert_se(proc_dir_open(&d) >= 0); - FOREACH_DIRENT(de, d, return) { + for (;;) { pid_t pid; - if (de->d_type != DT_DIR) - continue; + r = proc_dir_read(d, &pid); + assert_se(r >= 0); - if (parse_pid(de->d_name, &pid) < 0) - continue; + if (r == 0) /* EOF */ + break; - test_get_process_cmdline_one(pid); + test_pid_get_cmdline_one(pid); } } -static void test_get_process_comm_escape_one(const char *input, const char *output) { +static void test_pid_get_comm_escape_one(const char *input, const char *output) { _cleanup_free_ char *n = NULL; log_debug("input: <%s> — output: <%s>", input, output); assert_se(prctl(PR_SET_NAME, input) >= 0); - assert_se(get_process_comm(0, &n) >= 0); + assert_se(pid_get_comm(0, &n) >= 0); log_debug("got: <%s>", n); assert_se(streq_ptr(n, output)); } -TEST(get_process_comm_escape) { +TEST(pid_get_comm_escape) { _cleanup_free_ char *saved = NULL; - assert_se(get_process_comm(0, &saved) >= 0); + assert_se(pid_get_comm(0, &saved) >= 0); - test_get_process_comm_escape_one("", ""); - test_get_process_comm_escape_one("foo", "foo"); - test_get_process_comm_escape_one("012345678901234", "012345678901234"); - test_get_process_comm_escape_one("0123456789012345", "012345678901234"); - test_get_process_comm_escape_one("äöüß", "\\303\\244\\303\\266\\303\\274\\303\\237"); - test_get_process_comm_escape_one("xäöüß", "x\\303\\244\\303\\266\\303\\274\\303\\237"); - test_get_process_comm_escape_one("xxäöüß", "xx\\303\\244\\303\\266\\303\\274\\303\\237"); - test_get_process_comm_escape_one("xxxäöüß", "xxx\\303\\244\\303\\266\\303\\274\\303\\237"); - test_get_process_comm_escape_one("xxxxäöüß", "xxxx\\303\\244\\303\\266\\303\\274\\303\\237"); - test_get_process_comm_escape_one("xxxxxäöüß", "xxxxx\\303\\244\\303\\266\\303\\274\\303\\237"); + test_pid_get_comm_escape_one("", ""); + test_pid_get_comm_escape_one("foo", "foo"); + test_pid_get_comm_escape_one("012345678901234", "012345678901234"); + test_pid_get_comm_escape_one("0123456789012345", "012345678901234"); + test_pid_get_comm_escape_one("äöüß", "\\303\\244\\303\\266\\303\\274\\303\\237"); + test_pid_get_comm_escape_one("xäöüß", "x\\303\\244\\303\\266\\303\\274\\303\\237"); + test_pid_get_comm_escape_one("xxäöüß", "xx\\303\\244\\303\\266\\303\\274\\303\\237"); + test_pid_get_comm_escape_one("xxxäöüß", "xxx\\303\\244\\303\\266\\303\\274\\303\\237"); + test_pid_get_comm_escape_one("xxxxäöüß", "xxxx\\303\\244\\303\\266\\303\\274\\303\\237"); + test_pid_get_comm_escape_one("xxxxxäöüß", "xxxxx\\303\\244\\303\\266\\303\\274\\303\\237"); assert_se(prctl(PR_SET_NAME, saved) >= 0); } @@ -207,11 +208,11 @@ TEST(pid_is_unwaited) { } else { int status; - waitpid(pid, &status, 0); - assert_se(!pid_is_unwaited(pid)); + assert_se(waitpid(pid, &status, 0) == pid); + assert_se(pid_is_unwaited(pid) == 0); } - assert_se(pid_is_unwaited(getpid_cached())); - assert_se(!pid_is_unwaited(-1)); + assert_se(pid_is_unwaited(getpid_cached()) > 0); + assert_se(pid_is_unwaited(-1) < 0); } TEST(pid_is_alive) { @@ -224,11 +225,11 @@ TEST(pid_is_alive) { } else { int status; - waitpid(pid, &status, 0); - assert_se(!pid_is_alive(pid)); + assert_se(waitpid(pid, &status, 0) == pid); + assert_se(pid_is_alive(pid) == 0); } - assert_se(pid_is_alive(getpid_cached())); - assert_se(!pid_is_alive(-1)); + assert_se(pid_is_alive(getpid_cached()) > 0); + assert_se(pid_is_alive(-1) < 0); } TEST(personality) { @@ -253,7 +254,7 @@ TEST(personality) { #endif } -TEST(get_process_cmdline_harder) { +TEST(pid_get_cmdline_harder) { char path[] = "/tmp/test-cmdlineXXXXXX"; _cleanup_close_ int fd = -EBADF; _cleanup_free_ char *line = NULL; @@ -273,7 +274,7 @@ TEST(get_process_cmdline_harder) { #if HAVE_VALGRIND_VALGRIND_H /* valgrind patches open(/proc//cmdline) - * so, test_get_process_cmdline_harder fails always + * so, test_pid_get_cmdline_harder fails always * See https://github.com/systemd/systemd/pull/3555#issuecomment-226564908 */ if (RUNNING_ON_VALGRIND) { log_info("Skipping %s: running on valgrind", __func__); @@ -323,56 +324,56 @@ TEST(get_process_cmdline_harder) { assert_se(prctl(PR_SET_NAME, "testa") >= 0); - assert_se(get_process_cmdline(0, SIZE_MAX, 0, &line) == -ENOENT); + assert_se(pid_get_cmdline(0, SIZE_MAX, 0, &line) == -ENOENT); - assert_se(get_process_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "[testa]")); line = mfree(line); - assert_se(get_process_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_QUOTE, &line) >= 0); + assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_QUOTE, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "\"[testa]\"")); /* quoting is enabled here */ line = mfree(line); - assert_se(get_process_cmdline(0, 0, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 0, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "")); line = mfree(line); - assert_se(get_process_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); assert_se(streq(line, "…")); line = mfree(line); - assert_se(get_process_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); assert_se(streq(line, "[…")); line = mfree(line); - assert_se(get_process_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); assert_se(streq(line, "[t…")); line = mfree(line); - assert_se(get_process_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); assert_se(streq(line, "[te…")); line = mfree(line); - assert_se(get_process_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); assert_se(streq(line, "[tes…")); line = mfree(line); - assert_se(get_process_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); assert_se(streq(line, "[test…")); line = mfree(line); - assert_se(get_process_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); assert_se(streq(line, "[testa]")); line = mfree(line); - assert_se(get_process_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); assert_se(streq(line, "[testa]")); line = mfree(line); - assert_se(get_process_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args) >= 0); + assert_se(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args) >= 0); assert_se(strv_equal(args, STRV_MAKE("[testa]"))); args = strv_free(args); @@ -380,135 +381,135 @@ TEST(get_process_cmdline_harder) { assert_se(write(fd, "foo\0bar", 8) == 8); - assert_se(get_process_cmdline(0, SIZE_MAX, 0, &line) >= 0); + assert_se(pid_get_cmdline(0, SIZE_MAX, 0, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "foo bar")); line = mfree(line); - assert_se(get_process_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); assert_se(streq(line, "foo bar")); line = mfree(line); - assert_se(get_process_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args) >= 0); + assert_se(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args) >= 0); assert_se(strv_equal(args, STRV_MAKE("foo", "bar"))); args = strv_free(args); assert_se(write(fd, "quux", 4) == 4); - assert_se(get_process_cmdline(0, SIZE_MAX, 0, &line) >= 0); + assert_se(pid_get_cmdline(0, SIZE_MAX, 0, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "foo bar quux")); line = mfree(line); - assert_se(get_process_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "foo bar quux")); line = mfree(line); - assert_se(get_process_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "…")); line = mfree(line); - assert_se(get_process_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "f…")); line = mfree(line); - assert_se(get_process_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "fo…")); line = mfree(line); - assert_se(get_process_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "foo…")); line = mfree(line); - assert_se(get_process_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "foo …")); line = mfree(line); - assert_se(get_process_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "foo b…")); line = mfree(line); - assert_se(get_process_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "foo ba…")); line = mfree(line); - assert_se(get_process_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "foo bar…")); line = mfree(line); - assert_se(get_process_cmdline(0, 9, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 9, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "foo bar …")); line = mfree(line); - assert_se(get_process_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "foo bar q…")); line = mfree(line); - assert_se(get_process_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "foo bar qu…")); line = mfree(line); - assert_se(get_process_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "foo bar quux")); line = mfree(line); - assert_se(get_process_cmdline(0, 13, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 13, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "foo bar quux")); line = mfree(line); - assert_se(get_process_cmdline(0, 14, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 14, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "foo bar quux")); line = mfree(line); - assert_se(get_process_cmdline(0, 1000, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 1000, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "foo bar quux")); line = mfree(line); - assert_se(get_process_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args) >= 0); + assert_se(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args) >= 0); assert_se(strv_equal(args, STRV_MAKE("foo", "bar", "quux"))); args = strv_free(args); assert_se(ftruncate(fd, 0) >= 0); assert_se(prctl(PR_SET_NAME, "aaaa bbbb cccc") >= 0); - assert_se(get_process_cmdline(0, SIZE_MAX, 0, &line) == -ENOENT); + assert_se(pid_get_cmdline(0, SIZE_MAX, 0, &line) == -ENOENT); - assert_se(get_process_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "[aaaa bbbb cccc]")); line = mfree(line); - assert_se(get_process_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "[aaaa bbb…")); line = mfree(line); - assert_se(get_process_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "[aaaa bbbb…")); line = mfree(line); - assert_se(get_process_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); log_debug("'%s'", line); assert_se(streq(line, "[aaaa bbbb …")); line = mfree(line); - assert_se(get_process_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args) >= 0); + assert_se(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args) >= 0); assert_se(strv_equal(args, STRV_MAKE("[aaaa bbbb cccc]"))); args = strv_free(args); @@ -523,19 +524,19 @@ TEST(get_process_cmdline_harder) { assert_se(write(fd, CMDLINE1, sizeof CMDLINE1) == sizeof CMDLINE1); assert_se(ftruncate(fd, sizeof CMDLINE1) == 0); - assert_se(get_process_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line) >= 0); + assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line) >= 0); log_debug("got: ==%s==", line); log_debug("exp: ==%s==", EXPECT1); assert_se(streq(line, EXPECT1)); line = mfree(line); - assert_se(get_process_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line) >= 0); + assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line) >= 0); log_debug("got: ==%s==", line); log_debug("exp: ==%s==", EXPECT1p); assert_se(streq(line, EXPECT1p)); line = mfree(line); - assert_se(get_process_cmdline_strv(0, 0, &args) >= 0); + assert_se(pid_get_cmdline_strv(0, 0, &args) >= 0); assert_se(strv_equal(args, EXPECT1v)); args = strv_free(args); @@ -548,19 +549,19 @@ TEST(get_process_cmdline_harder) { assert_se(write(fd, CMDLINE2, sizeof CMDLINE2) == sizeof CMDLINE2); assert_se(ftruncate(fd, sizeof CMDLINE2) == 0); - assert_se(get_process_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line) >= 0); + assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line) >= 0); log_debug("got: ==%s==", line); log_debug("exp: ==%s==", EXPECT2); assert_se(streq(line, EXPECT2)); line = mfree(line); - assert_se(get_process_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line) >= 0); + assert_se(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line) >= 0); log_debug("got: ==%s==", line); log_debug("exp: ==%s==", EXPECT2p); assert_se(streq(line, EXPECT2p)); line = mfree(line); - assert_se(get_process_cmdline_strv(0, 0, &args) >= 0); + assert_se(pid_get_cmdline_strv(0, 0, &args) >= 0); assert_se(strv_equal(args, EXPECT2v)); args = strv_free(args); @@ -811,8 +812,8 @@ TEST(get_process_ppid) { assert_se(r >= 0); - assert_se(get_process_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &c1) >= 0); - assert_se(get_process_cmdline(ppid, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &c2) >= 0); + assert_se(pid_get_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &c1) >= 0); + assert_se(pid_get_cmdline(ppid, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &c2) >= 0); log_info("Parent of " PID_FMT " (%s) is " PID_FMT " (%s).", pid, c1, ppid, c2); diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c index 87c610bc73..3a30bfe042 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -207,7 +207,7 @@ static int process_one_password_file(const char *filename) { if (not_after > 0 && now(CLOCK_MONOTONIC) > not_after) return 0; - if (pid > 0 && !pid_is_alive(pid)) + if (pid > 0 && pid_is_alive(pid) <= 0) return 0; switch (arg_action) {