All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v11 tip/sched/core 0/6] Introduce per-CPU debugfs files
@ 2026-10-30 15:13 Aaron Tomlin
  2026-10-30 15:13 ` [PATCH v11 tip/sched/core 1/6] sched: Annotate rq->rd with __rcu and update lockless readers Aaron Tomlin
                   ` (5 more replies)
  0 siblings, 6 replies; 25+ messages in thread
From: Aaron Tomlin @ 2026-10-30 15:13 UTC (permalink / raw)
  To: mingo, peterz, juri.lelli, vincent.guittot
  Cc: paulmck, dietmar.eggemann, rostedt, bsegall, mgorman, vschneid,
	kprateek.nayak, zhanxusheng1024, neelx, atomlin, chjohnst,
	mproche, sean, steve, rishil1999, linux-kernel

Hi Peter, Juri, Ingo, Vincent,

The series has been re-verified and applies cleanly without conflict
against the current tip of tip/sched/core (commit b99b7f60c5b4).

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 introduces a prerequisite patch that annotates struct rq's rd
(root_domain) pointer with __rcu in kernel/sched/sched.h and introduces the
rcu_dereference_root_domain() helper macro (i.e. mirroring
rcu_dereference_sched_domain()), updating readers across the scheduler
subsystem to ensure Sparse compliance, correct memory ordering, and clean
Lockdep-RCU validation under both sched_domains_mutex and RCU-sched
contexts.

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
use-after-free when reading dl_bw->bw. This patch adds rcu_assign_pointer()
on the writer side in rq_attach_root() and uses guard(rcu)() with
rcu_dereference() in print_dl_rq().

Patch 3 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.

Patch 4 fixes both a time-of-check to time-of-use race condition and a
potential use-after-free in sched_show_numa(), where p->mm is checked
locklessly and then passed to P(mm->numa_scan_seq). If the task exits
concurrently via exit_mm(p), current->mm is set to NULL under task_lock(p)
before mmput() is called to free the struct mm_struct. Wrapping the p->mm
check and dereference in task_lock(p) eliminates both hazards.

Patch 5 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() and pre-fetches the next
pointer without memory barriers. Furthermore, because cfs_rq nodes are
re-linked on enqueue/dequeue without waiting for RCU grace periods,
concurrent list churn can cause backward jumps or infinite loops. This
patch introduces for_each_leaf_cfs_rq_rcu() using guard(rcu)(), bounds
traversal with a per-CPU circuit-breaker ceiling, and emits an explicit
truncation notice if the ceiling is reached.

Patch 6 introduces per-CPU debugfs entries under
/sys/kernel/debug/sched/cpu/cpu<N>/debug, 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 v10:

 - Removed redundant RCU_LOCKDEP_WARN() assertions from dl_bw_of() and
   dl_bw_cpus() in kernel/sched/deadline.c, as rcu_dereference_all_check()
   already validates RCU-sched and sched_domains_mutex lockdep state
   (K Prateek Nayak)

 - Reordered variable declarations in sched_set_rq_online() and
   sched_set_rq_offline() in kernel/sched/core.c (K Prateek Nayak)

 - Initialised struct root_domain *rd at declaration inside if (rq->online)
   in set_rq_offline() in kernel/sched/core.c (K Prateek Nayak)

 - Linked to v10: https://lore.kernel.org/lkml/20261030013817.753804-1-atomlin@atomlin.com/

Changes since v9:

 - Updated rq_attach_root() to use rcu_assign_pointer() when assigning
   rq->rd

 - Linked to v9: https://lore.kernel.org/lkml/20261029132511.712391-1-atomlin@atomlin.com/

Changes since v8:

 - Added guard(rcu)() to dl_task_needs_bw_move() to prevent false-positive
   warnings under CONFIG_PROVE_RCU when invoked from cpuset_can_attach()

 - Converted remaining direct rq->rd accessors across in add_nr_running(),
   __sched_setscheduler(), and dl_task_check_affinity() to use
   rcu_dereference_root_domain()

 - Linked to v8: https://lore.kernel.org/lkml/20260827194014.977758-1-atomlin@atomlin.com/

Changes since v7:

 - Removed incorrect rcu_dereference_protected() usages with
   lockdep_is_held(&rq->__lock) in favour of a newly introduced
   rcu_dereference_root_domain() helper, properly validating access under
   either sched_domains_mutex or RCU-sched read-side critical sections
   (Peter Zijlstra)

 - Restored the comment in check_update_overutilized_status() in
   kernel/sched/fair.c (Vincent Guittot)

 - Linked to v7: https://lore.kernel.org/lkml/20260826224238.936456-1-atomlin@atomlin.com/

Changes since v6:

 - Updated rq->rd accessors across kernel/sched/ to use
   rcu_dereference_sched() for lockless readers and
   rcu_dereference_protected() for lock-held paths, eliminating false
   Lockdep-RCU warnings under CONFIG_PROVE_RCU and all Sparse noderef
   warnings

 - Removed the __printf(3, 4) attribute from the !CONFIG_CGROUP_SCHED
   fallback stub of SEQ_printf_task_group_path() in kernel/sched/sched.h to
   prevent -Wformat build errors when CONFIG_CGROUP_SCHED is disabled
  
 - Expanded the commit changelog to clarify the per-CPU scope of
   SCHED_DEBUG_MAX_ITER and the RCU memory safety guarantees for recycled
   cfs_rq nodes

 - Linked to v6: https://lore.kernel.org/lkml/20260825184637.888364-1-atomlin@atomlin.com/

Changes since v5:

 - Rebased against tip/sched/core (sched-core-2026-08-17)

 - Linked to v5: https://lore.kernel.org/lkml/20260825141413.868997-1-atomlin@atomlin.com/

Changes since v4:

 - Added a new prerequisite patch to annotate struct rq's rd field with
   __rcu and updated lockless readers to use
   rcu_dereference()/rcu_dereference_sched()

 - Updated print_dl_rq() to use guard(rcu)() and rcu_dereference() on
   rq->rd (Daniel Vacek and K Prateek Nayak)

 - Replaced READ_ONCE(p->mm) with task_lock(p)/task_unlock(p) in
   sched_show_numa() to prevent use-after-free against concurrent exit_mm()
   and mmput()

 - Updated print_cfs_stats() to use guard(rcu)()

 - Increased SCHED_DEBUG_MAX_ITER from 1024 to 4096 and added an explicit
   truncation notice

 - Moved SEQ_printf() and SEQ_printf_task_group_path() to
   kernel/sched/sched.h, replaced strcpy() with strscpy(), and used
   IS_ENABLED(CONFIG_FAIR_GROUP_SCHED) with a typed static inline fallback
   stub

 - Corrected the "Fixes:" commit tag in Patch 5 to 039ae8bcf7a5 ("sched/fair:
   Fix O(nr_cgroups) in the load balancing path")

 - Linked to v4: https://lore.kernel.org/lkml/20260810015812.428999-1-atomlin@atomlin.com/

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 (6):
  sched: Annotate rq->rd with __rcu and update lockless readers
  sched/debug: Protect lockless rq->rd access in print_dl_rq()
  sched/debug: Protect lockless rq->curr access in print_cpu()
  sched/debug: Protect 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/core.c     | 23 ++++++++-----
 kernel/sched/deadline.c | 82 ++++++++++++++++++++++---------------------
 kernel/sched/debug.c    | 92 +++++++++++++++++++++++++++++--------------------
 kernel/sched/fair.c     | 60 ++++++++++++++++++++++++--------
 kernel/sched/rt.c       | 64 +++++++++++++++++++---------------
 kernel/sched/sched.h    | 58 +++++++++++++++++++++++++++++--
 kernel/sched/syscalls.c |  8 ++---
 kernel/sched/topology.c | 13 +++----
 8 files changed, 260 insertions(+), 140 deletions(-)

-- 
2.55.0

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2026-11-09 11:51 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-30 15:13 [PATCH v11 tip/sched/core 0/6] Introduce per-CPU debugfs files Aaron Tomlin
2026-10-30 15:13 ` [PATCH v11 tip/sched/core 1/6] sched: Annotate rq->rd with __rcu and update lockless readers Aaron Tomlin
2026-11-09  8:44   ` [tip: sched/core] " tip-bot2 for Aaron Tomlin
2026-11-09  9:28   ` [tip: sched/core] sched/core: " tip-bot2 for Aaron Tomlin
2026-11-09 11:51   ` tip-bot2 for Aaron Tomlin
2026-10-30 15:13 ` [PATCH v11 tip/sched/core 2/6] sched/debug: Protect lockless rq->rd access in print_dl_rq() Aaron Tomlin
2026-11-09  8:44   ` [tip: sched/core] " tip-bot2 for Aaron Tomlin
2026-11-09  9:28   ` tip-bot2 for Aaron Tomlin
2026-11-09 11:51   ` tip-bot2 for Aaron Tomlin
2026-10-30 15:13 ` [PATCH v11 tip/sched/core 3/6] sched/debug: Protect lockless rq->curr access in print_cpu() Aaron Tomlin
2026-11-09  8:43   ` [tip: sched/core] " tip-bot2 for Aaron Tomlin
2026-11-09  9:28   ` tip-bot2 for Aaron Tomlin
2026-11-09 10:02   ` tip-bot2 for Aaron Tomlin
2026-10-30 15:13 ` [PATCH v11 tip/sched/core 4/6] sched/debug: Protect p->mm access in sched_show_numa() Aaron Tomlin
2026-11-09  8:43   ` [tip: sched/core] " tip-bot2 for Aaron Tomlin
2026-11-09  9:28   ` tip-bot2 for Aaron Tomlin
2026-11-09 10:02   ` tip-bot2 for Aaron Tomlin
2026-10-30 15:13 ` [PATCH v11 tip/sched/core 5/6] sched/fair: Use list_for_each_entry_rcu() in print_cfs_stats() Aaron Tomlin
2026-11-09  8:43   ` [tip: sched/core] " tip-bot2 for Aaron Tomlin
2026-11-09  9:28   ` tip-bot2 for Aaron Tomlin
2026-11-09 10:02   ` tip-bot2 for Aaron Tomlin
2026-10-30 15:13 ` [PATCH v11 tip/sched/core 6/6] sched/debug: Introduce per-CPU debugfs files Aaron Tomlin
2026-11-09  8:43   ` [tip: sched/core] " tip-bot2 for Aaron Tomlin
2026-11-09  9:28   ` tip-bot2 for Aaron Tomlin
2026-11-09 10:02   ` tip-bot2 for Aaron Tomlin

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.