GhostLock, a stack-UAF that has existed in all Linux distributions for 15 years
GhostLock: A 15-Year Legacy Stack-UAF in the Linux Kernel
IonStack Part II presents an analysis of GhostLock, a critical stack-based Use-After-Free (UAF) vulnerability that remained undetected across every major Linux distribution for approximately a decade and a half.
🛡️ Vulnerability Summary
GhostLock (identified as CVE-2026-43499) was discovered by the VEGA team. This flaw is particularly dangerous because it requires no special privileges, no specific user namespaces, and no rare kernel configurations to trigger.
Quick Facts
| Attribute | Detail |
|---|---|
| CVE ID | CVE-2026-43499 |
| Vulnerability Type | Stack-Use-After-Free (UAF) |
| Affected Versions | through |
| Requirement | CONFIG_FUTEX_PI=y |
| Impact | Local Privilege Escalation (LPE) & Container Escape |
| Stability | |
| Bounty | \92,337$ (via Google kernelCTF) |
Capabilities of an Attacker
An unprivileged local user can leverage GhostLock to:
- Obtain a dangling pointer referencing kernel stack memory using standard threading system calls.
- Manipulate function tables to hijack the kernel's control flow.
- Ultimately escalate privileges to root.
🔍 Vulnerability Analysis
Overview
The origin of GhostLock traces back to a rework of the rtmutex (real-time mutex) logic in commit 8161239a8bcc, titled "rtmutex: Simplify PI algorithm and make highest prio task get lock". This architectural change introduced a subtle bug that persisted until April 2026, when it was finally addressed in commit 3bfdc63936dd.
The vulnerability resides within the remove_waiter() function located in kernel/locking/rtmutex.c.
The Technical Root Cause
The core of the issue is a mismatch between the assumptions made by a helper function and the context in which it is called.
The Logic Gap: The
remove_waiter()function was designed under the assumption that the thread currently executing (current) is the same thread that is the "waiter" being cleaned up. Consequently, it clears thepi_blocked_onfield of thecurrenttask.
While this logic holds true for the standard "slow path" of mutex acquisition, it fails during proxy locking.
The Proxy Lock Scenario
- Enqueueing: Through
rt_mutex_start_proxy_lock(), a task (the requeuer) can enqueue anrt_mutex_waiteron behalf of another task (the waiter) that is currently sleeping inFUTEX_WAIT_REQUEUE_PI. - The Trigger: A
FUTEX_CMP_REQUEUE_PIoperation proxies that waiter onto a target Priority Inheritance (PI) futex. - The Failure: If the kernel's
rtmutexchain walk detects a deadlock, a rollback occurs. This rollback callsremove_waiter()to dequeue the waiter. - The Bug: Because
remove_waiter()clearscurrent->pi_blocked_on, it clears the pointer for the requeuer, but not for the waiter.
Visualizing the Failure Flow
The Resulting Primitive
The waiter task continues to hold a pi_blocked_on pointer that references its own stack frame. However, the moment that waiter task returns to userspace, its kernel stack frame is popped and invalidated.
Any subsequent PI chain walk that encounters this task will follow that dangling pointer into freed stack memory, creating a powerful primitive for the attacker.
🛠️ Exploit & Mitigation
Exploit Strategy (High Level)
The transition from a dangling pointer to root access involves several complex steps:
- ASLR Bypass: Utilizing
PrefetchandCEA spraytechniques to leak kernel addresses. - Stack Forging: Using
PR_SET_MM_MAPto reuse the freed stack space and forge a "waiter" object. - Write Primitive: Converting the fake waiter into a limited write capability, aided by
inet6_protos[IPPROTO_UDP]. - Control Flow: Executing a pivot to
DirtyModeor a larger ROP chain to disable permissions.
Mitigation Checklist
To protect systems against GhostLock, administrators should ensure the following:
- Update Kernel: Upgrade to Linux v7.1 or the latest patched LTS version.
- Verify Patch: Ensure commit
3bfdc63936ddis applied. - Review Config: Check if
CONFIG_FUTEX_PIis enabled (if disabled, the system is not vulnerable).
The Fix
The patch corrects the logic in remove_waiter() by ensuring the function uses the actual waiter's task reference rather than the current task:
/* Pseudo-code of the fix */
// OLD:
// current->pi_blocked_on = NULL;
// NEW:
// waiter->task->pi_blocked_on = NULL;
GhostLock was a hidden danger for 15 years GhostLock is now mitigated in modern kernels.
📅 Timeline & Disclosure
- Introduced: (Linux 2.6.39)
- Discovered: 2026 by VEGA (Nebula Security)
- Patched: April 2026 (Linux 7.1)
- Public Disclosure: July 7, 2026