CVE-2026-98219: sched_ext: Close the pre-enable ops error claim window
In the Linux kernel, the following vulnerability has been resolved:
schedext: Close the pre-enable ops error claim window
scxallocandaddsched() publishes ops->priv before scxrootenableworkfn() switches the state to SCXENABLING. An error claimed via scxbpferrorbstr() from an associated BPF program in that window is consumed by scxdisableworkfn(), which takes the pre-enable shortcut in scxrootdisable(). The shortcut returns without any teardown and restores SCXDISABLED with an unconditional scxsetenablestate() xchg racing the enable workfn's own transition. The enable then completes with the claim consumed: the scheduler stays up but can never be disabled again, and bpfscxunreg() frees it while still in use, resulting in a use-after-free. Both WARNONONCE()s fire back to back:
WARNING: kernel/sched/ext/ext.c:7522 at scxrootenableworkfn+0xeec/0x1be0, CPU#3: scxenablehelp/276
WARNING: kernel/sched/ext/ext.c:6398 at scxrootdisable+0xb50/0xdb8, CPU#0: schedexthelpe/664
scxrootenableworkfn() switches to SCXENABLING before the scheduler allocation, so ops->priv is never visible while SCXDISABLED. The allocation failure path restores SCXDISABLED.
Affected Software
Event History
Frequently Asked Questions
What conditions are required for this issue to occur?
The race requires an associated BPF program to claim an error through scx_bpf_error_bstr() during the interval after ops->priv is published but before the scheduler state changes to SCX_ENABLING.
How can I identify a system that has encountered this failure?
The reported failure produces two WARN_ON_ONCE() warnings in close succession: one at scx_root_enable_workfn() in kernel/sched/ext/ext.c and another at scx_root_disable(). The scheduler may remain enabled but no longer be disableable, followed by a use-after-free when bpf_scx_unreg() frees it while it is still in use.
What does the resolved change do to prevent the race?
It transitions the scheduler to SCX_ENABLING before scheduler allocation, preventing ops->priv from being visible while the state is SCX_DISABLED. If allocation fails, the state is restored to SCX_DISABLED.