From f6793bbcf0e3f0a6daa77add96183b88d5ec2117 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 20 Nov 2024 12:02:46 +0100 Subject: [PATCH] killall: gracefully handle processes inserted into containers via nsenter -a "nsenter -a" doesn't migrate the specified process into the target cgroup (it really should). Thus the cgroup will remain in a cgroup that is (due to cgroup ns) outside our visibility. The kernel will report the cgroup path of such cgroups as starting with "/../". Detect that and print a reasonably error message instead of trying to resolve that. --- src/basic/cgroup-util.c | 4 ++++ src/shared/killall.c | 8 ++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 223bcdfbcfa..5370090f007 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -803,6 +803,10 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **ret_path) { if (!path) return -ENOMEM; + /* Refuse cgroup paths from outside our cgroup namespace */ + if (startswith(path, "/../")) + return -EUNATCH; + /* Truncate suffix indicating the process is a zombie */ e = endswith(path, " (deleted)"); if (e) diff --git a/src/shared/killall.c b/src/shared/killall.c index a08736480ef..184aec018bd 100644 --- a/src/shared/killall.c +++ b/src/shared/killall.c @@ -46,13 +46,17 @@ static bool argv_has_at(pid_t pid) { return c == '@'; } -static bool is_survivor_cgroup(const PidRef *pid) { +static bool is_in_survivor_cgroup(const PidRef *pid) { _cleanup_free_ char *cgroup_path = NULL; int r; assert(pidref_is_set(pid)); r = cg_pidref_get_path(/* root= */ NULL, pid, &cgroup_path); + if (r == -EUNATCH) { + log_warning_errno(r, "Process " PID_FMT " appears to originate in foreign namespace, ignoring.", pid->pid); + return true; + } if (r < 0) { log_warning_errno(r, "Failed to get cgroup path of process " PID_FMT ", ignoring: %m", pid->pid); return false; @@ -86,7 +90,7 @@ static bool ignore_proc(const PidRef *pid, bool warn_rootfs) { return true; /* also ignore processes where we can't determine this */ /* Ignore processes that are part of a cgroup marked with the user.survive_final_kill_signal xattr */ - if (is_survivor_cgroup(pid)) + if (is_in_survivor_cgroup(pid)) return true; r = pidref_get_uid(pid, &uid);