Linux Kernel Futex-PI rtmutex remove_waiter() Use-After-Free (CVE-2026-43499)
by MobiusM (PoC); reported by Yuan Tan, Yifan Wu, Juefei Pu, Xin Liu; fix by Keenan Dong, committed by Thomas Gleixner · 2026-07-05
- Severity
- High
- CVE
- CVE-2026-43499
- Category
- binary
- Affected product
- Linux kernel — kernel/locking/rtmutex.c, futex-PI subsystem (futex_requeue() / rt_mutex_start_proxy_lock())
- Affected versions
- Linux 2.6.39 through 6.18.x; fixed in 6.1.175, 6.6.140, 6.12.86, 6.18.27, 7.0.4
- Disclosed
- 2026-07-05
- Patch status
- patched
Tags
References
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-05 |
| Last Updated | 2026-06 |
| Author / Researcher | MobiusM (PoC); reported by Yuan Tan, Yifan Wu, Juefei Pu, Xin Liu; fix by Keenan Dong, committed by Thomas Gleixner |
| CVE / Advisory | CVE-2026-43499 |
| Category | binary |
| Severity | High |
| CVSS Score | 7.8 (CVSS 3.1, Local/Low complexity/Low privileges required — per upstream advisory) |
| Status | PoC |
| Tags | linux-kernel, android, use-after-free, futex, rtmutex, priority-inheritance, lpe, local, kernel-panic, ndk |
| Related | See also the “GhostLock” weaponized variant PoC: 2026-07-08_cve-2026-43499-ghostlock-nebula-security |
Affected Target
| Field | Value |
|---|---|
| Software / System | Linux kernel — kernel/locking/rtmutex.c, futex-PI subsystem (futex_requeue() / rt_mutex_start_proxy_lock()) |
| Versions Affected | Linux 2.6.39 through 6.18.x; fixed in 6.1.175, 6.6.140, 6.12.86, 6.18.27, 7.0.4 |
| Language / Platform | C, compiled/run on Android (arm64-v8a, NDK) in this PoC; generic Linux kernel bug |
| Authentication Required | Local (unprivileged) |
| Network Access Required | No — local only |
Summary
CVE-2026-43499 is a use-after-free in the Linux kernel’s remove_waiter() function (kernel/locking/rtmutex.c), which is shared between the ordinary rtmutex slow-unlock path and the futex priority-inheritance (PI) proxy-lock rollback path invoked from futex_requeue(). In the proxy-lock case the waiter being removed belongs to a different task than current, but remove_waiter() incorrectly operates on current, causing an rbtree dequeue without the correct task’s pi_lock held and leaving that task’s pi_blocked_on pointer dangling. This PoC (trigger.c) drives futex_requeue()/futex_lock_pi() on Android to reliably reproduce the bug, crashing the kernel with a documented panic in rt_mutex_adjust_prio_chain().
Vulnerability Details
Root Cause
remove_waiter() is called both from the standard rtmutex slow unlock path (where the waiter always belongs to current) and from rt_mutex_start_proxy_lock()’s rollback path when a futex-PI requeue operation fails partway through (where the waiter belongs to a different task that is being requeued onto the PI lock). The function assumes current is always the correct task to operate on. In the proxy-lock case this is wrong, producing three consequences:
- The waiter’s rbtree dequeue occurs without holding that waiter task’s
pi_lock, creating a race window. - The waiter task’s
pi_blocked_onfield is never cleared, leaving a dangling reference into freed/reused rtmutex waiter state. rt_mutex_adjust_prio_chain()subsequently walks/adjusts priority using the wrong task context.
This is tracked as CWE-416 (Use After Free). The upstream fix (commit 3bfdc63936dd4773109b7b8c280c0f3b5ae7d349, “rtmutex: Use waiter::task instead of current in remove_waiter()”) changes remove_waiter() to operate on waiter::task rather than unconditionally on current.
Attack Vector
- An unprivileged local process sets up a futex-PI proxy-lock scenario via
futex_requeue()combined withfutex_lock_pi()/do_futex(), arranging for the proxy-lock rollback path inrt_mutex_start_proxy_lock()to be hit. - The rollback invokes
remove_waiter()on the wrong task (currentinstead of the actual waiter task), dequeuing rbtree state without the properpi_lockand leavingpi_blocked_ondangling on the other task. - Subsequent futex/rtmutex operations that dereference the stale
pi_blocked_onpointer (viart_mutex_adjust_prio_chain()) operate on freed/inconsistent state — reliably reproduced by the includedtrigger.c, which crashes the kernel deterministically (seedmesg_crash.txt). - In a real exploitation scenario (beyond this repo’s crash-only PoC), controlled reallocation of the freed waiter/rtmutex state combined with the dangling pointer could be leveraged for kernel memory corruption and privilege escalation.
Impact
Local privilege escalation primitive via kernel use-after-free; this specific PoC demonstrates reliable kernel panic / denial of service (crash) on affected Android/Linux kernel builds, which is itself strong evidence of an exploitable UAF condition even without a full LPE chain in this repository.
Environment / Lab Setup
Target: Android device/emulator running an affected kernel (Linux 2.6.39–6.18.x,
unpatched).
Prerequisites: Android NDK 27, CMake >= 3.22, Ninja, adb.
Build:
cmake -B build -G Ninja
cmake --build build
Deploy & run:
adb push build/trigger /data/local/tmp/trigger
adb shell chmod +x /data/local/tmp/trigger
adb shell /data/local/tmp/trigger
Proof of Concept
PoC Script
See
trigger.candCMakeLists.txtin this folder.dmesg_crash.txtcontains the actual kernel panic captured from a vulnerable device.
| |
Running trigger on a vulnerable device drives the futex-PI requeue/proxy-lock rollback path in remove_waiter() and reliably panics the kernel with “Unable to handle kernel write to read-only memory”, crashing inside rt_mutex_adjust_prio_chain() as called from futex_lock_pi() → do_futex() → __arm64_sys_futex() (see dmesg_crash.txt for the full oops/backtrace).
Detection & Indicators of Compromise
dmesg / kernel log signature (see dmesg_crash.txt for the full capture):
"Unable to handle kernel write to read-only memory at virtual address ..."
PC is at rt_mutex_adjust_prio_chain+...
Call trace includes: futex_lock_pi -> do_futex -> __arm64_sys_futex
Kernel panic - not syncing: Oops: Fatal exception
Signs of compromise:
- Unexplained kernel panics/reboots referencing
rt_mutex_adjust_prio_chainor futex-PI code paths in dmesg/kernel crash logs. - Repeated calls to
futex()/FUTEX_LOCK_PI/FUTEX_REQUEUE_PIfrom an unprivileged process immediately preceding a crash or unexplained reboot. - On Android, presence of debug-snapshot/secdbg core dumps referencing rtmutex/futex symbols.
Remediation
| Action | Detail |
|---|---|
| Primary fix | Apply upstream commit 3bfdc63936dd4773109b7b8c280c0f3b5ae7d349 (“rtmutex: Use waiter::task instead of current in remove_waiter()”); update to Linux 6.1.175, 6.6.140, 6.12.86, 6.18.27, 7.0.4, or later. |
| Interim mitigation | No practical workaround short of patching — futex-PI is a core kernel synchronization primitive; monitor for the crash signature above and prioritize kernel updates on affected Android/Linux devices. |
References
Notes
Mirrored from https://github.com/MobiusM/CVE-2026-43499 on 2026-07-05.
| |