Skip to content

Commit dd6fc40

Browse files
devnexengregkh
authored andcommitted
sched_ext: idle: Recheck prev_cpu after narrowing allowed mask
commit b34c827 upstream. scx_select_cpu_dfl() narrows @Allowed to @cpus_allowed & @p->cpus_ptr when the BPF caller supplies a @cpus_allowed that differs from @p->cpus_ptr and @p doesn't have full affinity. However, @is_prev_allowed was computed against the original (wider) @cpus_allowed, so the prev_cpu fast paths could pick a @prev_cpu that is in @cpus_allowed but not in @p->cpus_ptr, violating the intended invariant that the returned CPU is always usable by @p. The kernel masks this via the SCX_EV_SELECT_CPU_FALLBACK fallback, but the behavior contradicts the documented contract. Move the @is_prev_allowed evaluation past the narrowing block so it tests against the final @Allowed mask. Fixes: ee9a4e9 ("sched_ext: idle: Properly handle invalid prev_cpu during idle selection") Cc: stable@vger.kernel.org # v6.16+ Assisted-by: Claude <noreply@anthropic.com> Signed-off-by: David Carlier <devnexen@gmail.com> Reviewed-by: Andrea Righi <arighi@nvidia.com> Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 6151967 commit dd6fc40

1 file changed

Lines changed: 6 additions & 6 deletions

File tree

kernel/sched/ext_idle.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -459,12 +459,6 @@ s32 scx_select_cpu_dfl(struct task_struct *p, s32 prev_cpu, u64 wake_flags,
459459

460460
preempt_disable();
461461

462-
/*
463-
* Check whether @prev_cpu is still within the allowed set. If not,
464-
* we can still try selecting a nearby CPU.
465-
*/
466-
is_prev_allowed = cpumask_test_cpu(prev_cpu, allowed);
467-
468462
/*
469463
* Determine the subset of CPUs usable by @p within @cpus_allowed.
470464
*/
@@ -481,6 +475,12 @@ s32 scx_select_cpu_dfl(struct task_struct *p, s32 prev_cpu, u64 wake_flags,
481475
}
482476
}
483477

478+
/*
479+
* Check whether @prev_cpu is still within the allowed set. If not,
480+
* we can still try selecting a nearby CPU.
481+
*/
482+
is_prev_allowed = cpumask_test_cpu(prev_cpu, allowed);
483+
484484
/*
485485
* This is necessary to protect llc_cpus.
486486
*/

0 commit comments

Comments
 (0)