[tip: sched/core] sched/debug: Protect lockless rq->curr access in print_cpu()

From: tip-bot2 for Aaron Tomlin

Date: Mon Nov 09 2026 - 04:38:12 EST


The following commit has been merged into the sched/core branch of tip:

Commit-ID: 06c4df428fe9a4e86d65f37d2e5c232607f29c8a
Gitweb: https://git.kernel.org/tip/06c4df428fe9a4e86d65f37d2e5c232607f29c8a
Author: Aaron Tomlin <atomlin@xxxxxxxxxxx>
AuthorDate: Fri, 30 Oct 2026 11:13:04 -04:00
Committer: Ingo Molnar <mingo@xxxxxxxxxx>
CommitterDate: Mon, 09 Nov 2026 10:23:48 +01:00

sched/debug: Protect lockless rq->curr access in print_cpu()

In print_cpu(), rq->curr is dereferenced locklessly to print the current
task's PID via task_pid_nr(rq->curr).

While accessing /sys/kernel/debug/sched/debug is inherently best-effort
only; rq->curr is indeed expected to change dynamically while
print_cpu() is executing. However, if the task currently running on the
CPU exits concurrently and its reference count drops to zero,
put_task_struct() calls call_rcu() to schedule
__put_task_struct_rcu_cb(). Because print_cpu() does not hold the RCU
read lock while dereferencing rq->curr, an RCU grace period can complete
concurrently and free the task structure via free_task(), creating a
potential use-after-free race condition.

Resolve this by reading rq->curr using rcu_dereference(rq->curr) inside an
RCU read-side critical section. Holding the RCU read lock delays the
invocation of __put_task_struct_rcu_cb() until after rcu_read_unlock(),
ensuring that the struct task_struct memory remains valid while being
accessed.

Reported-by: sashiko-bot <sashiko-bot@xxxxxxxxxx>
Signed-off-by: Aaron Tomlin <atomlin@xxxxxxxxxxx>
Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>
Signed-off-by: Ingo Molnar <mingo@xxxxxxxxxx>
Link: https://patch.msgid.link/20261030151307.768523-4-atomlin@xxxxxxxxxxx
---
kernel/sched/debug.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c
index 439e59b..be886ed 100644
--- a/kernel/sched/debug.c
+++ b/kernel/sched/debug.c
@@ -1204,7 +1204,10 @@ do { \
P(nr_switches);
P(nr_uninterruptible);
PN(next_balance);
- SEQ_printf(m, " .%-30s: %ld\n", "curr->pid", (long)(task_pid_nr(rq->curr)));
+ rcu_read_lock();
+ SEQ_printf(m, " .%-30s: %ld\n", "curr->pid",
+ (long)(task_pid_nr(rcu_dereference(rq->curr))));
+ rcu_read_unlock();
PN(clock);
PN(clock_task);
#undef P