Cloudanix VulnDB

CVE-2026-89517

None

CVSS

—

EPSS

0.2%

Published

Sep 11, 2026

CISA due date

—

Cloudanix analysis

Next patch cycle SSVC: Track

A bug in the Linux kernel’s CPU scheduler can freeze or crash machines that use certain advanced scheduling features when several programs compete for the same processor cores.

Exploitation
Local Privilege
Attacker needs
Local User
Complexity
Moderate
Impact
Denial Of Service
Component
OS kernel
Class
Race Condition
Remediation
Upgrade
Effort
Medium
Patch risk
Low

What it actually does

A race in the Linux kernel sched_ext pick path under SMT core scheduling corrupts per-runqueue core_pick state when dispatch drops the shared core-wide rq lock. Interleaved selections on sibling CPUs can NULL rq->core_pick (kernel NULL dereference) or commit a keep-previous-task decision against a task that has already been dequeued, leaving a non-runnable task on the CPU. That state deadlocks subsequent wakeups and produces hard hangs. The bug is local to the scheduler fast path: it does not by itself yield memory disclosure or privilege escalation, but it can panic or permanently stall the machine.

Why it matters to the business

Availability is the primary risk. Hosts that enable both sched_ext (custom BPF CPU schedulers) and core scheduling on SMT hardware can lock up or crash under a modest concurrent workload, forcing a hard reboot and interrupting any workloads on the box. Impact is concentrated on Linux estates that run experimental or production SCX schedulers (for example latency-sensitive or isolation-focused deployments); conventional CFS/EEVDF-only kernels are unaffected. Exploit maturity is none, EPSS is low and flat (~0.002 over 30 days), the CVE is not in CISA KEV, and it is not associated with ransomware. Residual risk is operational outage rather than compromise, but an unplanned kernel hang on a shared host or hypervisor still has high blast radius.

How an attack unfolds

An attacker with the ability to run unprivileged (or containerized) processes on a vulnerable kernel that has sched_ext and core scheduling enabled creates a pair of cookie-tagged tasks that bounce across SMT siblings. Core-wide pick_next_task() selects work for every sibling under one lock; sched_ext dispatch inside pick_task_scx() can drop that lock. Concurrent picks then overwrite each other's rq->core_pick or invalidate a keep-previous decision. The kernel either NULL-dereferences in the pick path or continues running a dequeued task, after which the next wakeup deadlocks and the machine hard-hangs—often within seconds under a ping-pong load. No remote service is required; local code execution or a noisy tenant workload is sufficient. Named threat actors and in-the-wild campaigns are not reported.

How to fix it

Apply the upstream sched_ext fix that forces RETRY_TASK whenever dispatch released the rq lock, uses rq->scx.lock_drop_seq to bound retries, skips nested dispatch when another dispatch is in flight, runs deferred balance work directly when picking for another rq, and gates the put_prev_task_scx() runnable-task warning to the non-core path. Upgrade to a distribution kernel that includes that commit (or a stable backport). If a patched package is not yet available: disable core scheduling, or unload/disable the sched_ext scheduler and revert to CFS/EEVDF; avoid cookie-based SMT isolation workloads on unpatched SMT hosts. Reboot onto the patched kernel to activate the change.

How to confirm the fix worked

Confirm the running kernel contains the sched_ext core-scheduling pick retry/lock_drop_seq fix (vendor advisory, uname -r vs. patched package, or presence of the lock_drop_seq logic in the sched_ext pick path). Verify CONFIG_SCHED_CLASS_EXT and core scheduling (sched_core) status: if either is off, the bug cannot fire. After patching, reboot and re-run SMT sibling loads that previously hung (cookie-tagged ping-pong) in a lab; the host should remain stable with no NULL deref in pick_next_task/pick_task_scx and no hard lockups. Inventory remaining unpatched SCX+core-sched SMT nodes before returning them to production.

Typical attack path

  1. Obtain local execution on a Linux host whose kernel builds sched_ext and has core scheduling enabled on SMT CPUs.
  2. Load or rely on an SCX scheduler so picks go through pick_task_scx()/dispatch.
  3. Place cookie-tagged tasks on sibling hardware threads so core-wide selection runs under the shared rq lock.
  4. Generate concurrent pick/dispatch interleavings that drop the rq lock mid-selection (ping-pong / yield / migrate load).
  5. Trigger rq->core_pick corruption: NULL dereference (oops/panic) or a dequeued task left running.
  6. Observe wakeup deadlock or hard lockup; the host becomes unresponsive until reset.

How to detect it

This defect crashes or hangs the kernel; it does not leave a persistent implant. Hunt historical availability events, not C2. Review kernel logs (journald/kmsg/serial console/vmcore/kdump) around unexplained reboots, NMI watchdog events, and hung-task detector reports. Look for NULL pointer dereferences in pick_next_task, pick_task_scx, or core-scheduling helpers touching rq->core_pick; hard LOCKUP / soft lockup / hung_task traces on SMT CPUs while an SCX scheduler was loaded; and put_prev_task_scx warnings about a runnable task left behind. Correlate with sched_ext being enabled (scx_* kthreads, BPF scheduler load) and core scheduling cookies. Crash dumps showing a dequeued task still current on an rq are consistent with exploitation or accidental triggering. Absence of these artifacts does not prove the host was never exposed—silent hard hangs may only appear as ping/SSH loss and a reset. No named APT activity is associated.

  • kernel NULL pointer dereference, address: 0000000000000000
  • pick_task_scx
  • pick_next_task
  • rq->core_pick
  • put_prev_task_scx
  • sched_ext
  • scx_
  • BUG: soft lockup
  • hard LOCKUP
  • watchdog: BUG: soft lockup - CPU#
  • Kernel panic - not syncing: Fatal exception
  • hung_task: blocked for more than
  • RETRY_TASK
  • lock_drop_seq

What your security team should do

  • Prioritize kernel upgrades on SMT hosts that run sched_ext and core scheduling; treat unpatched SCX production nodes as availability-critical even though EPSS/KEV are low.
  • Until patched, disable core scheduling or SCX on those hosts and block cookie-isolation / sibling-pinning workloads.
  • Track distro stable backports; there is no userspace-only workaround.
  • Add kernel-oops and hard/soft-lockup alerting for sched_ext/core_pick stacks so a hang is not mistaken for an application freeze.
  • After patching, verify the new kernel is actually running (kexec/live-patch gaps) and retire any custom SCX builds that lack the retry-on-lock-drop change.

The record

In the Linux kernel, the following vulnerability has been resolved: sched_ext: Fix rq->core_pick corruption under core scheduling Core scheduling's pick_next_task() picks what to run on every SMT sibling of the core in a single pass under the shared core-wide rq lock. The selection state is consistent only while the lock is held continuously, so ->pick_task() originally could not release it. However, since 4c95380701f5 ("sched/ext: Fold balance_scx() into pick_task_scx()"), sched_ext runs dispatch from inside the pick and dispatching can drop the rq lock. To support this, pick_next_task() has been updated to restart the whole selection when a pick returns RETRY_TASK after releasing the lock. When selections on the same core interleave through the dropped lock, they corrupt each other's state: one clears the other's rq->core_pick leading to a NULL deref, or invalidates its keep-the-previous-task decision leaving a dequeued task running, which deadlocks the next wakeup and matches the reported hard hangs. A cookied ping-pong load on an SMT machine makes the interleavings frequent and kills the kernel within seconds. Fix it by making the pick return RETRY_TASK whenever dispatch released the rq lock, so that a selection only ever commits picks made under a continuously held lock. The previous patch's rq->scx.lock_drop_seq counts the releases. A dispatch that touched nothing never releases the lock and its verdict, including "nothing to run", stands: retries are bounded, each following a dispatch that actually did something, and an idle CPU does not loop. If another dispatch is already in flight on the rq, skip dispatching and pick from what is already queued locally - the in-flight dispatch has released the lock, so its own selection will retry and re-pick this rq, while returning RETRY_TASK here would only spin on the lock that dispatch needs to finish. Balance callbacks must run in the context that queued them, so they can only be queued on the CPU's own rq. When dispatching for another rq, run the deferred work directly instead - that rq may consume all its picks through the core-sched fast path and never queue the callback itself. The put_prev_task_scx() warning about a runnable task being left behind assumed that dispatch ran as part of the very pick that is switching away. That now only holds on the non-core path, so gate it and drop the cookie-match test, which is always true without core scheduling, from its condition.

Affected packages

Ecosystem Package Introduced Fixed