ZeroHour

CVE-2026-90003

large

Use-after-free in Linux kernel futex requeue PI on PREEMPT_RT allows local privilege escalation

CVSS 3.1
7.8 high
EPSS
Published
()
Modified
AI analysis

The Linux kernel futex subsystem contains a use-after-free race in the FUTEX_CMP_REQUEUE_PI path on PREEMPT_RT (real-time preemption) kernels: the futex_q used by futex_wait_requeue_pi() lives on the waiter's task stack, and an early wakeup (timeout or signal) can race with a PI requeue so that the requeue task calls rcuwait_wake_up() after the waiter has already returned from the syscall and the stack object is gone, producing a KASAN slab-out-of-bounds report in futex_requeue_pi_complete(). The race is triggered by local code using the FUTEX_CMP_REQUEUE_PI operation in a way that makes the waiter wake up while a requeue is in progress. A successful exploit corrupts kernel memory, and the CVSS 3.1 score of 7.8 (local vector, low privileges, high confidentiality/integrity/availability impact) is consistent with local privilege escalation or kernel crash. Only systems running Linux kernels built with PREEMPT_RT enabled are affected; standard (non-RT) kernel configurations are not implicated by this report. No public proof-of-concept is known, the flaw is not in CISA's KEV catalog, and no in-the-wild exploitation has been reported.

What to do: Update affected real-time Linux kernels with the futex requeue PI fix via your distribution or vendor's backport (the patch skips the rcuwait_wake_up() call in the Q_REQUEUE_PI_LOCKED case), and check whether your kernel configuration enables PREEMPT_RT to determine if you are exposed. Until patched, limit local untrusted code execution on real-time systems, and watch distro/kernel.org advisories for the fixed package versions since the source data does not name them.

Affected
Linux (kernel.org) Linux kernel, futex subsystem (FUTEX_CMP_REQUEUE_PI path)
Estimated exposure
large≈100,000–1,000,000 systems running PREEMPT_RT/real-time Linux kernels (order-of-magnitude estimate) — No public scan enumerates PREEMPT_RT deployments, so the estimate is based on deployment patterns: real-time Linux is widely used in industrial control, robotics, telecom, medical and automotive devices (and PREEMPT_RT is now a mainline…

Order-of-magnitude estimate by the model from install counts, market share and public scan data it knows; verify before quoting.

Description

In the Linux kernel, the following vulnerability has been resolved: futex: Prevent rcuwait use-after-free during requeue PI On PREEMPT_RT, FUTEX_CMP_REQUEUE_PI can trigger a KASAN report (slab-out-of-bounds) in futex_requeue_pi_complete() invocation of rcuwait_wake_up(). The futex_q used by futex_wait_requeue_pi() is allocated on the waiter's stack. An early wakeup can race with a PI requeue as follows: waiter requeue task ------ ------------ futex_wait_requeue_pi() futex_do_wait() schedule() futex_requeue futex_proxy_trylock_atomic() futex_requeue_pi_prepare() Q_REQUEUE_PI_NONE -> Q_REQUEUE_PI_IN_PROGRESS * timeout/ signal wakes waiter * futex_requeue_pi_wakeup_sync() Q_REQUEUE_PI_IN_PROGRESS -> Q_REQUEUE_PI_WAIT requeue_pi_wake_futex futex_requeue_pi_complete() cmpxchg Q_REQUEUE_PI_WAIT -> Q_REQUEUE_PI_LOCKED rcuwait_wait_event() if (atomic_read(&q->requeue_state) != Q_REQUEUE_PI_WAIT) break /* no schedule() */ /* q.pi_state->owner == current */ futex_private_hash_put() /* return from syscall */ rcuwait_wake_up(&q->requeue_wait) /* q is gone */ futex_requeue_pi_complete() publishes Q_REQUEUE_PI_LOCKED before calling rcuwait_wake_up(). The waiter observes this state in rcuwait_wait_event() before invoking schedule() in rcuwait_wait_event(). Here, the waiter is free leave the syscall before requeue task can complete the wake. To address this race skip rcuwait_wake_up() in the Q_REQUEUE_PI_LOCKED case. This state is only published by requeue_pi_wake_futex(), which saves q->task before futex_requeue_pi_complete() and wakes the waiter via wake_up_state(). This wake is intended to wake the waiter from its futex_do_wait() sleep. If the waiter is still sleeping there, it can not get into the Q_REQUEUE_PI_WAIT state (and require this removed wake). Should the waiter be woken up from futex_do_wait() by other means (as in this example) and sleep in futex_requeue_pi_wakeup_sync() then the wake_up_state() from requeue_pi_wake_futex() will wake it, too. Should the waiter task terminate before wake_up_state() had a chance to wake the task then the task pointer does not become invalid because the futex_hash_bucket::lock is held and the task pointer is RCU protected. [bigeasy: Updated comment and commit message]

Vector
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

In the news

No ingested article mentions this CVE yet.