public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Rik van Riel <riel@surriel.com>
To: linux-kernel@vger.kernel.org
Cc: kernel-team@meta.com, Ingo Molnar <mingo@redhat.com>,
	Peter Zijlstra <peterz@infradead.org>,
	Juri Lelli <juri.lelli@redhat.com>,
	Vincent Guittot <vincent.guittot@linaro.org>,
	Steven Rostedt <rostedt@goodmis.org>
Subject: [PATCH] sched/cpuacct: fix use-after-free in cpuacct_account_field()
Date: Sat, 4 Apr 2026 22:47:42 -0400	[thread overview]
Message-ID: <20260404224742.56d8df3e@fangorn> (raw)

cpuacct_css_free() calls free_percpu() on ca->cpustat and ca->cpuusage,
then kfree(ca). However, a timer interrupt on another CPU can
concurrently access this data through cpuacct_account_field(), which
walks the cpuacct hierarchy via task_ca()/parent_ca() and performs
__this_cpu_add(ca->cpustat->cpustat[index], val).

The race window exists because put_css_set_locked() drops the CSS
reference (css_put) before the css_set is RCU-freed (kfree_rcu). This
means the CSS percpu_ref can reach zero and trigger the css_free chain
while readers obtained the CSS pointer from the old css_set that is
still visible via RCU.

Although css_free_rwork_fn is already called after one RCU grace period,
the css_set -> CSS reference drop in put_css_set_locked() creates a
window where the CSS free chain races with readers still holding the
old css_set reference.

With KASAN enabled, free_percpu() unmaps shadow pages, so the
KASAN-instrumented __this_cpu_add hits an unmapped shadow page
(PMD=0), causing a page fault in IRQ context that cascades into an
IRQ stack overflow.

Fix this by deferring the actual freeing of percpu data and the cpuacct
struct to an RCU callback via call_rcu(), ensuring that all concurrent
readers in RCU read-side critical sections (including timer tick
handlers) have completed before the memory is freed.

Found in an AI driven syzkaller run. The bug did not repeat in the
14 hours since this patch was applied.

Signed-off-by: Rik van Riel <riel@surriel.com>
Assisted-by: Claude:claude-opus-4.6 syzkaller
Fixes: 3eba0505d03a ("sched/cpuacct: Remove redundant RCU read lock")
Cc: stable@kernel.org
---
 kernel/sched/cpuacct.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/kernel/sched/cpuacct.c b/kernel/sched/cpuacct.c
index ca9d52cb1ebb..b6e7b34de616 100644
--- a/kernel/sched/cpuacct.c
+++ b/kernel/sched/cpuacct.c
@@ -28,6 +28,7 @@ struct cpuacct {
 	/* cpuusage holds pointer to a u64-type object on every CPU */
 	u64 __percpu	*cpuusage;
 	struct kernel_cpustat __percpu	*cpustat;
+	struct rcu_head	rcu;
 };
 
 static inline struct cpuacct *css_ca(struct cgroup_subsys_state *css)
@@ -84,15 +85,22 @@ cpuacct_css_alloc(struct cgroup_subsys_state *parent_css)
 }
 
 /* Destroy an existing CPU accounting group */
-static void cpuacct_css_free(struct cgroup_subsys_state *css)
+static void cpuacct_free_rcu(struct rcu_head *rcu)
 {
-	struct cpuacct *ca = css_ca(css);
+	struct cpuacct *ca = container_of(rcu, struct cpuacct, rcu);
 
 	free_percpu(ca->cpustat);
 	free_percpu(ca->cpuusage);
 	kfree(ca);
 }
 
+static void cpuacct_css_free(struct cgroup_subsys_state *css)
+{
+	struct cpuacct *ca = css_ca(css);
+
+	call_rcu(&ca->rcu, cpuacct_free_rcu);
+}
+
 static u64 cpuacct_cpuusage_read(struct cpuacct *ca, int cpu,
 				 enum cpuacct_stat_index index)
 {
-- 
2.52.0



             reply	other threads:[~2026-04-05  2:47 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-05  2:47 Rik van Riel [this message]
2026-04-07  7:58 ` [PATCH] sched/cpuacct: fix use-after-free in cpuacct_account_field() Peter Zijlstra
2026-04-07 18:59   ` Tejun Heo
2026-04-08 13:58     ` Rik van Riel

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=20260404224742.56d8df3e@fangorn \
    --to=riel@surriel.com \
    --cc=juri.lelli@redhat.com \
    --cc=kernel-team@meta.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=vincent.guittot@linaro.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