All of lore.kernel.org
 help / color / mirror / Atom feed
From: Aaron Tomlin <atomlin@atomlin.com>
To: mingo@redhat.com, peterz@infradead.org, juri.lelli@redhat.com,
	vincent.guittot@linaro.org
Cc: dietmar.eggemann@arm.com, rostedt@goodmis.org,
	bsegall@google.com, mgorman@suse.de, vschneid@redhat.com,
	kprateek.nayak@amd.com, zhanxusheng1024@gmail.com,
	neelx@suse.com, chjohnst@mail.com, mproche@mail.com,
	sean@ashe.io, steve@abita.co, linux-kernel@vger.kernel.org
Subject: [PATCH v4 0/5] sched/debug: Introduce per-CPU debugfs files
Date: Sun,  9 Aug 2026 21:58:07 -0400	[thread overview]
Message-ID: <20260810015812.428999-1-atomlin@atomlin.com> (raw)

Hi Peter, Juri, Ingo, Vincent,

This patch series addresses a few pre-existing memory safety and list
traversal concurrency issues in scheduler debugfs handlers, and introduces
per-CPU debugfs files under /sys/kernel/debug/sched/cpu/cpu<N>/debug.

Patch 1 fixes a potential use-after-free in print_cpu() where rq->curr is
dereferenced locklessly to output the running task's PID. If the task exits
concurrently and its reference count drops to zero, put_task_struct()
schedules __put_task_struct_rcu_cb() via call_rcu(). Without holding an RCU
read lock, an RCU grace period can elapse concurrently and free the task
structure via free_task(), leading to a use-after-free race condition. This
patch protects rq->curr access using rcu_dereference() inside an RCU
read-side critical section, ensuring sparse compliance.

Patch 2 fixes a use-after-free in print_dl_rq() where cpu_rq(cpu)->rd is
dereferenced locklessly to display deadline bandwidth statistics. During
CPU hot-unplug or cgroup cpuset repartitioning events,
partition_sched_domains() calls rq_attach_root() to detach the CPU from its
root_domain and schedules free_rootdomain() via call_rcu(). Without an RCU
read lock, an RCU grace period can resolve concurrently while debugfs reads
the file, allowing free_rootdomain() to execute kfree() and causing a UAF
when reading dl_bw->bw. This patch adds rcu_assign_pointer() on the writer
side in rq_attach_root() and fetches rq->rd using READ_ONCE() inside an RCU
read-side critical section in print_dl_rq().

Patch 3 fixes a time-of-check to time-of-use race condition in
sched_show_numa(), where p->mm is checked locklessly and then passed to
P(mm->numa_scan_seq), causing a double-evaluation of p->mm. If the task
exits concurrently (exit_mm(p)), p->mm can be set to NULL on another CPU
between the check and the macro expansion, causing a NULL-pointer
dereference crash. This patch reads p->mm once into a local variable using
READ_ONCE(p->mm) before checking and dereferencing its numa_scan_seq field.

Patch 4 fixes an RCU traversal violation in print_cfs_stats() where
rq->leaf_cfs_rq_list is traversed locklessly using
for_each_leaf_cfs_rq_safe(), which expands to list_for_each_entry_safe().
Although leaf_cfs_rq_list is modified using list_add_rcu(),
list_for_each_entry_safe() lacks READ_ONCE(), allowing compiler reordering
or re-fetching that can cause readers to observe newly inserted cfs_rq
nodes before internal fields are initialised. This patch introduces
for_each_leaf_cfs_rq_rcu() using list_for_each_entry_rcu() and adds a hard
iteration ceiling to prevent RCU stalls under list churn.

Patch 5 introduces per-CPU debugfs entries under
/sys/kernel/debug/sched/cpu/, allowing targeted inspection of an individual
CPU's runqueue on demand. If the target CPU is currently offline, reading
its file returns -ENODEV.


Changes since v3:

 - Updated Patch 1 to use rcu_dereference(rq->curr) instead of READ_ONCE()
   to preserve __rcu

 - Added missing writer-side RCU publication barrier (rcu_assign_pointer())
   in rq_attach_root() for Patch 2

 - Added Patch 3 to fix a TOCTOU condition in sched_show_numa() using
   READ_ONCE(p->mm)

 - Added a safety iteration ceiling in print_cfs_stats() for Patch 4 to
   prevent unbounded list iteration and RCU stalls under heavy
   leaf_cfs_rq_list churn

 - Linked to v3: https://lore.kernel.org/lkml/20260808235522.380038-1-atomlin@atomlin.com/

Changes since v2:

 - Protected lockless rq->curr dereferencing in print_cpu() with
   rcu_read_lock() and READ_ONCE()

 - Protected lockless rq->rd dereferencing in print_dl_rq() against CPU
   hot-unplug and cgroup cpuset repartitioning races

 - Introduced for_each_leaf_cfs_rq_rcu() using list_for_each_entry_rcu()
   for lockless leaf_cfs_rq_list iteration

 - Linked to v2: https://lore.kernel.org/lkml/20260728205238.18447-1-atomlin@atomlin.com/

Changes since v1:

 - Reframed commit message motivation around targeted interactive
   debugging on large SMP topologies (Peter Zijlstra and Zhan Xusheng)

 - Gated sched_debug_cpu_show() with a cpu_online(cpu) check
   returning -ENODEV when target CPU is offline (Zhan Xusheng)

 - Linked to v1: https://lore.kernel.org/lkml/20260728020309.6169-1-atomlin@atomlin.com/

Aaron Tomlin (5):
  sched/debug: Protect lockless rq->rd access in print_dl_rq()
  sched/debug: Protect lockless rq->curr access in print_cpu()
  sched/debug: Protect lockless p->mm access in sched_show_numa()
  sched/fair: Use list_for_each_entry_rcu() in print_cfs_stats()
  sched/debug: Introduce per-CPU debugfs files

 kernel/sched/debug.c    | 66 +++++++++++++++++++++++++++++++++++++----
 kernel/sched/fair.c     | 17 +++++++++--
 kernel/sched/topology.c |  2 +-
 3 files changed, 76 insertions(+), 9 deletions(-)

-- 
2.55.0


             reply	other threads:[~2026-08-10  1:58 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-10  1:58 Aaron Tomlin [this message]
2026-08-10  1:58 ` [PATCH v4 1/5] sched/debug: Protect lockless rq->rd access in print_dl_rq() Aaron Tomlin
2026-08-10  6:50   ` K Prateek Nayak
2026-08-11  1:29     ` Aaron Tomlin
2026-08-10 13:53   ` Daniel Vacek
2026-08-11  1:34     ` Aaron Tomlin
2026-08-10  1:58 ` [PATCH v4 2/5] sched/debug: Protect lockless rq->curr access in print_cpu() Aaron Tomlin
2026-08-10  1:58 ` [PATCH v4 3/5] sched/debug: Protect lockless p->mm access in sched_show_numa() Aaron Tomlin
2026-08-10  1:58 ` [PATCH v4 4/5] sched/fair: Use list_for_each_entry_rcu() in print_cfs_stats() Aaron Tomlin
2026-08-10  1:58 ` [PATCH v4 5/5] sched/debug: Introduce per-CPU debugfs files Aaron Tomlin

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=20260810015812.428999-1-atomlin@atomlin.com \
    --to=atomlin@atomlin.com \
    --cc=bsegall@google.com \
    --cc=chjohnst@mail.com \
    --cc=dietmar.eggemann@arm.com \
    --cc=juri.lelli@redhat.com \
    --cc=kprateek.nayak@amd.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mgorman@suse.de \
    --cc=mingo@redhat.com \
    --cc=mproche@mail.com \
    --cc=neelx@suse.com \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=sean@ashe.io \
    --cc=steve@abita.co \
    --cc=vincent.guittot@linaro.org \
    --cc=vschneid@redhat.com \
    --cc=zhanxusheng1024@gmail.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.