]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
bpf: Do not limit bpf_cgroup_from_id to current's namespace
authorKumar Kartikeya Dwivedi <memxor@gmail.com>
Mon, 15 Sep 2025 03:26:17 +0000 (03:26 +0000)
committerAlexei Starovoitov <ast@kernel.org>
Mon, 15 Sep 2025 17:53:15 +0000 (10:53 -0700)
The bpf_cgroup_from_id kfunc relies on cgroup_get_from_id to obtain the
cgroup corresponding to a given cgroup ID. This helper can be called in
a lot of contexts where the current thread can be random. A recent
example was its use in sched_ext's ops.tick(), to obtain the root cgroup
pointer. Since the current task can be whatever random user space task
preempted by the timer tick, this makes the behavior of the helper
unreliable.

Refactor out __cgroup_get_from_id as the non-namespace aware version of
cgroup_get_from_id, and change bpf_cgroup_from_id to make use of it.

There is no compatibility breakage here, since changing the namespace
against which the lookup is being done to the root cgroup namespace only
permits a wider set of lookups to succeed now. The cgroup IDs across
namespaces are globally unique, and thus don't need to be retranslated.

Reported-by: Dan Schatzberg <dschatzberg@meta.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Acked-by: Tejun Heo <tj@kernel.org>
Link: https://lore.kernel.org/r/20250915032618.1551762-2-memxor@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
include/linux/cgroup.h
kernel/bpf/helpers.c
kernel/cgroup/cgroup.c

index b18fb5fcb38e239347c1be4b5af9f74f14c767c4..b08c8e62881cd9ecde62927590f565dbae220ddb 100644 (file)
@@ -650,6 +650,7 @@ static inline void cgroup_kthread_ready(void)
 }
 
 void cgroup_path_from_kernfs_id(u64 id, char *buf, size_t buflen);
+struct cgroup *__cgroup_get_from_id(u64 id);
 struct cgroup *cgroup_get_from_id(u64 id);
 #else /* !CONFIG_CGROUPS */
 
index c0c0764a20251c6ca5f6319abe303b83adc76f58..51229aba53181896112092b2c16acf3d8043ad8d 100644 (file)
@@ -2546,7 +2546,7 @@ __bpf_kfunc struct cgroup *bpf_cgroup_from_id(u64 cgid)
 {
        struct cgroup *cgrp;
 
-       cgrp = cgroup_get_from_id(cgid);
+       cgrp = __cgroup_get_from_id(cgid);
        if (IS_ERR(cgrp))
                return NULL;
        return cgrp;
index 312c6a8b55bb73d2780ca4b3ed02669bb3062bb9..6c2d20ac697c3c1efb8df6d810e38619ad4869b9 100644 (file)
@@ -6343,15 +6343,15 @@ void cgroup_path_from_kernfs_id(u64 id, char *buf, size_t buflen)
 }
 
 /*
- * cgroup_get_from_id : get the cgroup associated with cgroup id
+ * __cgroup_get_from_id : get the cgroup associated with cgroup id
  * @id: cgroup id
  * On success return the cgrp or ERR_PTR on failure
- * Only cgroups within current task's cgroup NS are valid.
+ * There are no cgroup NS restrictions.
  */
-struct cgroup *cgroup_get_from_id(u64 id)
+struct cgroup *__cgroup_get_from_id(u64 id)
 {
        struct kernfs_node *kn;
-       struct cgroup *cgrp, *root_cgrp;
+       struct cgroup *cgrp;
 
        kn = kernfs_find_and_get_node_by_id(cgrp_dfl_root.kf_root, id);
        if (!kn)
@@ -6373,6 +6373,22 @@ struct cgroup *cgroup_get_from_id(u64 id)
 
        if (!cgrp)
                return ERR_PTR(-ENOENT);
+       return cgrp;
+}
+
+/*
+ * cgroup_get_from_id : get the cgroup associated with cgroup id
+ * @id: cgroup id
+ * On success return the cgrp or ERR_PTR on failure
+ * Only cgroups within current task's cgroup NS are valid.
+ */
+struct cgroup *cgroup_get_from_id(u64 id)
+{
+       struct cgroup *cgrp, *root_cgrp;
+
+       cgrp = __cgroup_get_from_id(id);
+       if (IS_ERR(cgrp))
+               return cgrp;
 
        root_cgrp = current_cgns_cgroup_dfl();
        if (!cgroup_is_descendant(cgrp, root_cgrp)) {