The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH] sched/core: Don't pin the idle task in migrate_disable_switch()
@ 2026-08-06  7:17 Krystian Slowik
  2026-08-06  7:22 ` Peter Zijlstra
  0 siblings, 1 reply; 4+ messages in thread
From: Krystian Slowik @ 2026-08-06  7:17 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Juri Lelli, Vincent Guittot
  Cc: Dietmar Eggemann, Steven Rostedt, Ben Segall, Mel Gorman,
	Valentin Schneider, K Prateek Nayak, linux-kernel,
	Krystian Slowik, stable

Since commit 650952d3fb38 ("sched: Make __do_set_cpus_allowed() use the
sched_change pattern"), do_set_cpus_allowed() dequeues and re-enqueues
the target task through the sched_change guard whenever it is queued.

The idle task counts as queued: init_idle() sets
idle->on_rq = TASK_ON_RQ_QUEUED. But the idle sched class implements no
real dequeue_task() (only the "bad: scheduling from the idle thread!"
debug stub, which even drops and re-takes the rq lock in the middle of
the guarded section) and no enqueue_task() at all, so running the guard
on the idle task jumps through a NULL pointer in sched_change_end():

  bad: scheduling from the idle thread!
  CPU: 3 UID: 0 PID: 0 Comm: swapper/3 Kdump: loaded Not tainted 7.0.0-28-generic #28-Ubuntu PREEMPT(lazy)
  Call Trace:
   dequeue_task_idle+0x29/0x50
   dequeue_task+0xfb/0x300
   sched_change_begin+0x1ff/0x240
   migrate_disable_switch.isra.0+0xf8/0x190
   __schedule+0xdd/0x650
   schedule_idle+0x22/0x40
  BUG: kernel NULL pointer dereference, address: 0000000000000000
  #PF: supervisor instruction fetch in kernel mode
  RIP: 0010:0x0
  Call Trace:
   enqueue_task+0x89/0x1d0
   sched_change_end+0x18e/0x1d0
   migrate_disable_switch.isra.0+0x11e/0x190
   __schedule+0xdd/0x650
   schedule_idle+0x22/0x40
   do_idle+0xb6/0xf0
   cpu_startup_entry+0x29/0x30
   start_secondary+0x125/0x180

The path is reachable since commit 942b8db96500 ("sched: Fix
migrate_disable_switch() locking") moved migrate_disable_switch() to
the top of __schedule(), where it runs on every schedule out of the
idle loop rather than only on an actual context switch: any
migrate_disable() taken in the idle loop (e.g. from a tracing or BPF
callback) that is still held when the idle task schedules triggers the
pinning path.

Pinning the idle task is meaningless to begin with: it is a per-CPU
task that can never migrate. Skip it. This also keeps
___migrate_enable() unreachable for the idle task, since its cpus_ptr
is never repointed.

The check uses p == rq->idle rather than is_idle_task(), because the
latter also matches idle-injection threads (PF_IDLE), which are
ordinary queueable tasks.

Observed in production on two separate x86-64 machines running the
Ubuntu 7.0.0-28 kernel, both panicking from the idle loop with the
oops above.

Fixes: 650952d3fb38 ("sched: Make __do_set_cpus_allowed() use the sched_change pattern")
Cc: <stable@vger.kernel.org> # v7.0+
Signed-off-by: Krystian Slowik <me@krystianslowik.com>
---
 kernel/sched/core.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 9622670..823af64 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -2461,6 +2461,10 @@ static void migrate_disable_switch(struct rq *rq, struct task_struct *p)
 	if (p->cpus_ptr != &p->cpus_mask)
 		return;
 
+	/* The per-CPU idle task never migrates, there is nothing to pin. */
+	if (p == rq->idle)
+		return;
+
 	scoped_guard (task_rq_lock, p)
 		do_set_cpus_allowed(p, &ac);
 }
-- 
2.54.0


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

end of thread, other threads:[~2026-08-06 14:14 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-06  7:17 [PATCH] sched/core: Don't pin the idle task in migrate_disable_switch() Krystian Slowik
2026-08-06  7:22 ` Peter Zijlstra
2026-08-06  9:01   ` Krystian Slowik
2026-08-06 14:13     ` Peter Zijlstra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox