]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
cgroup-util: Don't try to open pidfd for pids from cgroup.threads 33084/head
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 29 May 2024 20:03:38 +0000 (22:03 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 30 May 2024 08:30:36 +0000 (10:30 +0200)
Opening pidfds for non thread group leaders only works from 6.9 onwards with PIDFD_THREAD. On
older kernels or without PIDFD_THREAD pidfd_open() fails with EINVAL. Since we might read non
thread group leader IDs from cgroup.threads, we introduce and set CGROUP_NO_PIDFD to avoid
trying open pidfd's for them and instead use the pid as is.

src/basic/cgroup-util.c
src/basic/cgroup-util.h

index be7f7c787d56746f37fed633e2a48bb55caeaadf..553ee6075aa671c9225961bfe687e1ce56773d3a 100644 (file)
@@ -149,6 +149,11 @@ int cg_read_pidref(FILE *f, PidRef *ret, CGroupFlags flags) {
                 if (pid == 0)
                         return -EREMOTE;
 
+                if (FLAGS_SET(flags, CGROUP_NO_PIDFD)) {
+                        *ret = PIDREF_MAKE_FROM_PID(pid);
+                        return 1;
+                }
+
                 r = pidref_set_pid(ret, pid);
                 if (r >= 0)
                         return 1;
@@ -352,7 +357,7 @@ static int cg_kill_items(
                 for (;;) {
                         _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
 
-                        r = cg_read_pidref(f, &pidref, /* flags = */ 0);
+                        r = cg_read_pidref(f, &pidref, flags);
                         if (r < 0)
                                 return RET_GATHER(ret, log_debug_errno(r, "Failed to read pidref from cgroup '%s': %m", path));
                         if (r == 0)
@@ -425,7 +430,11 @@ int cg_kill(
         if (r == 0)
                 return ret;
 
-        r = cg_kill_items(path, sig, flags, s, log_kill, userdata, "cgroup.threads");
+        /* Opening pidfds for non thread group leaders only works from 6.9 onwards with PIDFD_THREAD. On
+         * older kernels or without PIDFD_THREAD pidfd_open() fails with EINVAL. Since we might read non
+         * thread group leader IDs from cgroup.threads, we set CGROUP_NO_PIDFD to avoid trying open pidfd's
+         * for them and instead use the regular pid. */
+        r = cg_kill_items(path, sig, flags|CGROUP_NO_PIDFD, s, log_kill, userdata, "cgroup.threads");
         if (r < 0)
                 return log_debug_errno(r, "Failed to kill processes in cgroup '%s' item cgroup.threads: %m", path);
 
index 29417b39ad5948b68606ced678af5758ed18bbdd..a8871785b60826af5f526918aa7b3731c370a870 100644 (file)
@@ -188,6 +188,7 @@ typedef enum CGroupFlags {
         CGROUP_IGNORE_SELF        = 1 << 1,
         CGROUP_REMOVE             = 1 << 2,
         CGROUP_DONT_SKIP_UNMAPPED = 1 << 3,
+        CGROUP_NO_PIDFD           = 1 << 4,
 } CGroupFlags;
 
 int cg_enumerate_processes(const char *controller, const char *path, FILE **ret);