[PATCH v3 1/4] sched/debug: Protect lockless rq->curr access in print_cpu()

From: Aaron Tomlin

Date: Sat Aug 08 2026 - 19:56:00 EST


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 READ_ONCE() 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.

Fixes: 02968ccf7b80 ("sched: add /proc/sched_debug file")
Reported-by: sashiko-bot <sashiko-bot@xxxxxxxxxx>
Signed-off-by: Aaron Tomlin <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 40584b27ea0c..78fc02d71710 100644
--- a/kernel/sched/debug.c
+++ b/kernel/sched/debug.c
@@ -1126,7 +1126,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(READ_ONCE(rq->curr))));
+ rcu_read_unlock();
PN(clock);
PN(clock_task);
#undef P
--
2.55.0