Linux cgroups development
 help / color / mirror / Atom feed
From: Bradley Morgan <brads@mainlining.org>
To: "Jérémy Jean" <Jeremy.Jean@oss.cyber.gouv.fr>,
	"Tejun Heo" <tj@kernel.org>,
	"Johannes Weiner" <hannes@cmpxchg.org>,
	"Michal Koutný " <mkoutny@suse.com>
Cc: cgroups@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] cgroup: prevent use-after-free during namespace root replacement
Date: Wed, 23 Sep 2026 22:05:24 +0100	[thread overview]
Message-ID: <60C5456D-CE52-4FF3-9B1E-865EF916ED8C@mainlining.org> (raw)
In-Reply-To: <20260923204935.2253203-2-Jeremy.Jean@oss.cyber.gouv.fr>

On 23 September 2026 21:49:36 BST, "Jérémy Jean"
<Jeremy.Jean@oss.cyber.gouv.fr> wrote:
>copy_cgroup_ns() pins the creator's css_set, but cgroup_post_fork()
>replaces root_cset and releases the namespace's reference to that css_set
>after the child is visible to pid and pidfd lookups. A task joining the
>new namespace can race with this replacement and access the original
>css_set or its cgroup after they are freed.
>
>KASAN reports:
>
>  BUG: KASAN: slab-use-after-free in kernfs_get.part.0+0x47/0x60
>  Write of size 4 at addr ff1100000379f320 by task ns-path-probe/69
>   kernfs_walk_and_get_ns+0x1cc/0x280
>   cgroup_get_from_path+0xfb/0x340
>   nft_socket_cgroup_subtree_level+0x14/0x1a0
>
>Keep the initial root pinned until namespace destruction, taking a
>separate reference to the final root only when the roots differ.

Why would this be bad?

>
>Fixes: ef2c41cf38a7 ("clone3: allow spawning processes into cgroups")
>Assisted-by: LLM
>Signed-off-by: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr>
>---
> include/linux/cgroup_namespace.h | 2 ++
> kernel/cgroup/cgroup.c           | 9 ++++++---
> kernel/cgroup/namespace.c        | 3 +++
> 3 files changed, 11 insertions(+), 3 deletions(-)
>
>diff --git a/include/linux/cgroup_namespace.h b/include/linux/cgroup_namespace.h
>index 78a8418..f36ec1a 100644
>--- a/include/linux/cgroup_namespace.h
>+++ b/include/linux/cgroup_namespace.h
>@@ -9,6 +9,8 @@ struct cgroup_namespace {
> 	struct user_namespace	*user_ns;
> 	struct ucounts		*ucounts;
> 	struct css_set          *root_cset;
>+	/* Preserve the root observed before cgroup_post_fork() updates it. */
>+	struct css_set		*initial_root_cset;
> };
> 
> extern struct cgroup_namespace init_cgroup_ns;
>diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
>index 227d097..c3cb258 100644
>--- a/kernel/cgroup/cgroup.c
>+++ b/kernel/cgroup/cgroup.c
>@@ -247,6 +247,7 @@ struct cgroup_namespace init_cgroup_ns = {
> 	.ns		= NS_COMMON_INIT(init_cgroup_ns),
> 	.user_ns	= &init_user_ns,
> 	.root_cset	= &init_css_set,
>+	.initial_root_cset = &init_css_set,
> };
> 
> static struct file_system_type cgroup2_fs_type;
>@@ -7131,9 +7132,11 @@ void cgroup_post_fork(struct task_struct *child,
> 	if (kargs->flags & CLONE_NEWCGROUP) {
> 		struct css_set *rcset = child->nsproxy->cgroup_ns->root_cset;
> 
>-		get_css_set(cset);
>-		child->nsproxy->cgroup_ns->root_cset = cset;
>-		put_css_set(rcset);
>+		/* Both possible roots must remain pinned for namespace readers. */
>+		if (rcset != cset) {
>+			get_css_set(cset);
>+			WRITE_ONCE(child->nsproxy->cgroup_ns->root_cset, cset);
>+		}
> 	}
> 
> 	/* Cgroup has to be killed so take down child immediately. */
>diff --git a/kernel/cgroup/namespace.c b/kernel/cgroup/namespace.c
>index ea4ee13..1153ea4 100644
>--- a/kernel/cgroup/namespace.c
>+++ b/kernel/cgroup/namespace.c
>@@ -37,6 +37,8 @@ void free_cgroup_ns(struct cgroup_namespace *ns)
> {
> 	ns_tree_remove(ns);
> 	put_css_set(ns->root_cset);
>+	if (ns->initial_root_cset != ns->root_cset)
>+		put_css_set(ns->initial_root_cset);
> 	dec_cgroup_namespaces(ns->ucounts);
> 	put_user_ns(ns->user_ns);
> 	ns_common_free(ns);
>@@ -84,6 +86,7 @@ struct cgroup_namespace *copy_cgroup_ns(u64 flags,
> 	new_ns->user_ns = get_user_ns(user_ns);
> 	new_ns->ucounts = ucounts;
> 	new_ns->root_cset = cset;
>+	new_ns->initial_root_cset = cset;
> 
> 	ns_tree_add(new_ns);
> 	return new_ns;
>

--- Thanks!
"I'm not a very positive person" - Linus torvalds

  reply	other threads:[~2026-09-23 21:05 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-23 20:49 [PATCH] cgroup: prevent use-after-free during namespace root replacement Jérémy Jean
2026-09-23 21:05 ` Bradley Morgan [this message]
2026-09-23 23:56 ` Tejun Heo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=60C5456D-CE52-4FF3-9B1E-865EF916ED8C@mainlining.org \
    --to=brads@mainlining.org \
    --cc=Jeremy.Jean@oss.cyber.gouv.fr \
    --cc=cgroups@vger.kernel.org \
    --cc=hannes@cmpxchg.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mkoutny@suse.com \
    --cc=tj@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox