The Short Version
What it is: GhostLock (CVE-2026-43499) is a use-after-free in the Linux kernel’s futex priority-inheritance code, the locking feature behind glibc’s PTHREAD_PRIO_INHERIT mutexes. A cleanup step clears the wrong thread’s bookkeeping, leaving a live thread pointing at already-freed memory. Unusually, that memory sits on the kernel stack, not the heap where most such bugs live. Jump to the Long Version →
Impact: Local privilege escalation to root. Nebula Security’s public full-chain exploit reaches root from an unprivileged process in about five seconds at roughly 97% reliability. We reproduced the trigger and local DoS across Debian 11/12/13, EL7, and EL10; assume any affected kernel is root-exploitable, not just DoS-prone. Jump to the Long Version →
Severity: CVSS 7.8 (High). Local vector, low complexity, no user interaction, and a highly reliable public LPE chain on supported targets. Red Hat rates it Important. Jump to the Long Version →
Who’s affected: The only prerequisite is CONFIG_FUTEX_PI=y, on by default in every major distribution; no special capabilities, namespaces, or hardware needed. Introduced in Linux 2.6.39-rc1 (May 2011), with the vulnerable range running through v7.1-rc1, so nearly every production kernel qualifies. Jump to the Long Version →
Related flaw: A follow-up change, 74e144274af3 (CVE-2026-53166), was later reverted upstream because of a regression. Verify GhostLock coverage through CVE-2026-43499 and the primary fix 3bfdc63936dd. Jump to the Long Version →
Status: An N-day, not a zero-day. Reported April 18, fixed upstream April 20 (3bfdc63936dd), and backported May 4, all before the July 7 public disclosure. A working exploit is public and the flaw is already in the security press. Jump to the Long Version →
Do this now: There is no clean host-wide runtime mitigation; the vulnerable feature is compiled in and cannot be disabled on a running kernel. Apply a fixed vendor kernel or a KernelCare rebootless patch. In containers, a seccomp filter blocking the futex PI operations closes the trigger, at the cost of breaking workloads that use those locks. Jump to the Long Version →
Need to Patch Without Scheduling Another Emergency Reboot?
KernelCare applies Linux kernel security patches without downtime, workload disruption, or emergency maintenance windows.
KernelCare status (2026-07-09, 14:00 UTC): Debian 13, the full EL9 family (RHEL, AlmaLinux, Rocky, Oracle, plus AlmaLinux LTS and FIPS 9.6), Ubuntu 24.04, and Proxmox VE 8 are live in the main feed. Debian 12 and the EL10 family are in the testing feed. Amazon Linux 2023 is built but not yet released; Debian 11 and EL7 remain pending. Updated as releases land.
The Long Version
Two things will tempt you to file this ticket as low priority, and both are wrong.
The first is the age of the code. GhostLock lives in a locking routine that shipped in May 2011. A bug that sat quietly for fifteen years reads like a theoretical curiosity, the kind of finding that wins a conference slot and never touches a production host. That framing is comfortable and incorrect. The bug is reachable from an unprivileged process on a default kernel, and there is a public full-chain exploit that turns it into a root shell in seconds.
The second is the word “futex.” A futex (fast userspace mutex) is the kernel building block that libraries like glibc use to implement locks between threads. It sounds like deep plumbing that most applications never touch directly, and that is true, but the feature at the center of this bug, priority-inheritance locking, is not niche. CONFIG_FUTEX_PI is enabled by default on every major distribution, glibc uses it for PTHREAD_PRIO_INHERIT mutexes, and the vulnerable path is reachable without capabilities, namespaces, or special hardware. If your kernel is in the affected range and built with the default config, the surface is present.
GhostLock is the second entry in Nebula Security’s “IonStack” research series, disclosed publicly on July 7, 2026 by the team it credits as VEGA, with a full writeup, a bug-list entry, and a full-chain public proof of concept. It earned a Google kernelCTF reward of $92,337 on June 30. We picked it up on the morning of July 8, and a KernelCare engineer began cross-distro reproduction the same day.
One framing to hold onto before the details: this is a mainline bug, not a distribution quirk. Any kernel from 2.6.39-rc1 through 7.1-rc1 built with futex PI carries the vulnerable code. The published exploit is target-specific in its final stages, but the underlying defect is close to universal.
How GhostLock Works
Start with the piece of the kernel involved. When a thread waits on a priority-inheritance lock, the kernel tracks that relationship in a small record called a waiter, and it notes on the waiting thread which lock it is blocked on (a field named pi_blocked_on). Cleaning that bookkeeping up correctly matters, because if a thread walks away still marked as blocked on a lock that no longer exists, the kernel is holding a pointer to nothing.
The cleanup routine, remove_waiter(), was written for the simple case: one thread cleaning up its own wait. It assumes the thread doing the cleanup, which the kernel calls current, is the same thread that was waiting. A more advanced operation called requeue-PI breaks that assumption. Requeue-PI moves a waiting thread from one lock to another (it is how condition variables are implemented efficiently), which means the thread running the cleanup is the one doing the moving, not the one that was waiting.
Here is the mistake. When the kernel detects that a requeue would create a deadlock (a cycle where each thread waits on the next) and bails out with an error, the rollback path calls remove_waiter(), and remove_waiter() clears current->pi_blocked_on, the mover’s record, instead of the real waiter’s. The waiting thread is never cleaned up. When it returns to userspace, its pi_blocked_on still points into its own stack frame, which the kernel has since reclaimed for other use. That dangling pointer into freed stack memory is the use-after-free.
At a high level the exploit builds on that as follows:
[Unprivileged process, three threads/futexes]
│ stage a deadlock cycle so the kernel takes the buggy rollback path
▼
[remove_waiter() clears the wrong thread's record → a live thread points into its own freed stack frame]
│
▼
[Reclaim that freed frame with attacker-controlled data → forge a fake waiter record]
│
▼
[Trigger the cleanup again → write one attacker-chosen pointer into a kernel network table]
│
▼
[Point that table entry at attacker code → send one IPv6 UDP packet to run it]
▼
[Flip a system setting (core_pattern) so a crash handler runs as root → root shell]
Filling in the mechanism for readers who want it: the attacker stages the deadlock with three threads and futexes using the FUTEX_LOCK_PI, FUTEX_WAIT_REQUEUE_PI, and FUTEX_CMP_REQUEUE_PI operations, which forces the -EDEADLK (deadlock) return and the buggy rollback. They then reclaim the freed stack frame using PR_SET_MM_MAP, a process-control call that lets a program set fields the kernel copies onto its own stack, filling that memory with a forged rt_mutex_waiter record. Driving the kernel’s waiter-tree cleanup then turns into a single controlled pointer write, aimed at inet6_protos[IPPROTO_UDP], the table entry that tells the kernel which function handles incoming IPv6 UDP packets. The attacker points that entry at a “pivot” instruction placed at a fixed, predictable address (the CPU Entry Area, a per-CPU region that always lives at a known location), then sends an IPv6 UDP packet to invoke it. That hands control to a return-oriented programming chain (stitching together existing kernel code fragments to run arbitrary logic), and the final step flips the permissions on the core_pattern setting, which controls what program runs when a process crashes, so the attacker’s crash handler executes as root.
The functions involved are remove_waiter(), rt_mutex_start_proxy_lock(), and rt_mutex_adjust_prio_chain() in kernel/locking/rtmutex.c. The bug class is a kernel-stack use-after-free leading to local privilege escalation. It is worth pausing on “stack” there: most exploitable use-after-free bugs corrupt heap objects, where the layout is comparatively easy to groom. Reclaiming a specific freed stack frame with controlled contents is harder and less common, which is part of why this bug is both interesting and, in the researcher’s hands, still reliable.
What the Upstream Fix Changes
The primary fix is a one-line correction. Before the patch, the deadlock rollback cleared the wrong thread’s blocking record. After it, remove_waiter() clears waiter->task->pi_blocked_on (the real waiter’s record) rather than current->pi_blocked_on (the mover’s), so the unwind no longer leaves a live thread pointing at freed stack memory.
Conceptually:
Before: deadlock rollback → clear the mover's record → real waiter left pointing at freed memory → use-after-free
After: deadlock rollback → clear the real waiter's record → nothing left dangling
The upstream commit is 3bfdc63936dd (“rtmutex: Use waiter::task instead of current in remove_waiter()”). A follow-up change, 74e144274af3, was tracked separately as CVE-2026-53166 but was later reverted upstream because of a regression. It should not be treated as a second required GhostLock fix.
Because this is a small, self-contained locking-path change with no change to any data-structure layout, it is a clean rebootless patch candidate across kernel families.
Who Is Affected
GhostLock affects Linux systems built with CONFIG_FUTEX_PI=y, which is every major distribution’s default. The vulnerable code was introduced in commit 8161239a8bcc in Linux 2.6.39-rc1 (May 2011), and the vulnerable range runs through v7.1-rc1. In practice the impact is effectively universal: any kernel in that range built with futex PI.
Confirmed affected, trigger and local DoS reproduced by the KernelCare team with the public PoC:
- Debian 13 (now fixed, see below)
- Debian 12, vulnerable and not yet fixed
- Debian 11, vulnerable with no errata yet
- Enterprise Linux 7, DoS reproduced
- Enterprise Linux 10, DoS reproduced
Full-chain root: the researcher demonstrated root publicly at roughly 97% reliability. The weaponized exploit component is target-specific, carrying per-target memory offsets baked into its source. Our cross-distro verification exercised the trigger and use-after-free, not per-target root on each distribution. The safe working assumption is that any affected kernel is exploitable to root by a motivated attacker, not merely subject to DoS.
The Enterprise Linux picture needs care. As of July 8, Red Hat’s public CVE page lists all RHEL kernels (6, 7, 8, 9, and 10, including the real-time kernel-rt) as Affected, threat severity Important, with no errata released yet. That page changed during the day: earlier on July 8 it showed RHEL as not vulnerable, and any early “EL not affected” read was based on that now-superseded version. This is a case where reading the advisory once and moving on would have produced the wrong answer.
Red Hat’s technical fix has already landed silently in CentOS Stream (the rolling preview of the next RHEL kernels). Stream 9 was fixed in kernel-5.14.0-716.el9 and was vulnerable at kernel-5.14.0-699.el9. Stream 10 was fixed in kernel-6.12.0-239.el10 and was vulnerable at kernel-6.12.0-224.el10. Because CloudLinux 9 and 10 track the AlmaLinux and EL9/EL10 kernels, that Stream fix maps to those flavors, so the practical task is to check which side of the fixed-versus-vulnerable kernel boundary your currently shipping general kernel sits on. The EL7 and EL8 boundaries are not yet confirmed.
Mitigate Now
Here it is straight: there is no clean, general, host-wide runtime mitigation.
The only prerequisite for the bug is CONFIG_FUTEX_PI, and that is a build-time option with no runtime switch. It is required by glibc priority-inheritance mutexes, so it cannot be disabled on a running production kernel without breaking userspace programs that rely on those locks. There is no module to blacklist and no setting to flip.
That leaves patching and one workload-specific lever.
Containers and sandboxed workloads. A seccomp policy (the Linux facility for filtering which system calls a program may make) that blocks the futex priority-inheritance operations, FUTEX_LOCK_PI, FUTEX_WAIT_REQUEUE_PI, and FUTEX_CMP_REQUEUE_PI, closes the trigger. A robust filter has to cover the variants too, the futex_time64 syscall and architecture-specific syscall numbers, plus FUTEX_LOCK_PI2 on newer kernels, or the block can be sidestepped. The cost is that it breaks any workload that uses priority-inheritance mutexes, so test before deploying. This lever is also what makes the “container escape” framing real: unprivileged code inside a container reaches the bug unless the runtime already filters these futex operations.
Everywhere else. There is no host-wide mitigation short of applying the vendor kernel update or the KernelCare rebootless patch.
Decision moment. If you run containers or sandboxes and can tolerate the loss of priority-inheritance locks, deploy the seccomp filter as an interim block while you schedule the real fix. For general-purpose hosts, the only real answer is a fixed kernel or a rebootless patch, so move those to the front of the queue and isolate untrusted local execution until one lands. Prioritize the already-shipping Debian 13 and EL9 updates, along with the Ubuntu 24.04, Proxmox VE 8, and AlmaLinux specialty builds, and use the testing feed where appropriate for Debian 12 and EL10 while their production-feed promotion is pending.
Prioritized Remediation Checklist
- Track this as CVE-2026-43499 (GhostLock), and confirm the running kernel or rebootless patchlivepatch includes the primary fix, 3bfdc63936dd. The follow-up change tracked as CVE-2026-53166 was reverted upstream and is not required to confirm GhostLock coverage.
- Treat every kernel in the 2.6.39-rc1 through 7.1-rc1 range built with
CONFIG_FUTEX_PIas affected until proven otherwise. - Prioritize hosts where local isolation is the security boundary: shared hosting, multi-tenant nodes, CI runners, and container and developer hosts running untrusted code.
- For Enterprise Linux, check which side of the fixed-versus-vulnerable kernel boundary each host sits on rather than trusting a single advisory read. Stream 9 fixed at
kernel-5.14.0-716.el9, Stream 10 fixed atkernel-6.12.0-239.el10; EL7 and EL8 boundaries not yet confirmed. - Where you cannot patch immediately and the workload allows it, apply a seccomp filter blocking the futex priority-inheritance operations in containers and sandboxes.
- Do not disable
CONFIG_FUTEX_PIon a running kernel; it breaks glibc priority-inheritance mutexes and is not a supported mitigation. - Apply the available Debian 13, EL9, Ubuntu 24.04, Proxmox VE 8, and AlmaLinux specialty-build fixes now, and use the testing feed for Debian 12 and EL10 while continuing to track Debian 11, Amazon Linux 2023, and EL7 as coverage lands.
- Hunt for
core_patternchanges, rtmutex-path kernel warnings, and unexplained privilege gains, and treat clean file hashes as insufficient evidence about the host. - Apply a fixed vendor kernel and reboot, or use the KernelCare rebootless patch for the exact running kernel, prioritizing the hosts hardest to reboot.
Detection
GhostLock leaves no reliable on-disk signature. The corruption happens in kernel memory, and the documented finish changes a kernel setting rather than modifying files, so file-integrity tooling can stay clean after exploitation. That pushes detection into behavioral territory. The following signals are derived from the published exploit chain, and each is a lead, not proof:
- Unexpected changes to
/proc/sys/kernel/core_pattern, or to its permissions, especially a handler that runs an external program on crash. The public chain ends by abusingcore_patternto reach root. - Unprivileged processes running tight loops of futex priority-inheritance operations (
FUTEX_LOCK_PI,FUTEX_WAIT_REQUEUE_PI,FUTEX_CMP_REQUEUE_PI) across multiple threads, consistent with forcing the deadlock path. - Kernel oops or warnings in the rtmutex (realtime-mutex) code, around
remove_waiter(),rt_mutex_start_proxy_lock(), orrt_mutex_adjust_prio_chain(), with no matching hardware fault. - Use of
PR_SET_MM_MAPby processes that have no legitimate reason to rewrite their own memory layout, close in time to the above. - A local account or service gaining privileges shortly after a burst of futex and rtmutex instability, with no matching sudo or login event.
Review recent kernel messages:
journalctl -k --since "24 hours ago" | grep -Ei 'rtmutex|pi_blocked|remove_waiter|BUG|WARNING'
The absence of these messages does not prove a host is patched or uncompromised. A careful attacker can avoid tripping a warning, and a vulnerable path may simply not have been exercised yet. If untrusted or semi-trusted local code ran on an affected host during the exposure window, treat the host as warranting a closer look, including new accounts, altered auth configuration, and unexpected services, rather than reading clean file hashes as evidence of safety.
Why GhostLock Matters
GhostLock is a local privilege escalation, not remote code execution. Nobody roots your server from the internet with this alone. For the environments it actually lands in, that is thin comfort.
Shared hosting runs customer code. CI runners run whatever the last pull request told them to. Container and Kubernetes nodes run workloads at varying trust levels, and multi-tenant hosts exist specifically to keep tenants apart. In every one of those, a local privilege escalation is the event the whole design is meant to prevent. It converts code that was allowed to run into code running as root where it never should have.
The reason it is easy to misjudge is the reason it is dangerous. Three plausible signals all point toward “safe” and all mislead. The bug’s age reads like a museum piece, when it is reachable on a default kernel today. The futex feature reads like a niche corner, when it is compiled into essentially every distribution and used by glibc’s standard locks. And an advisory checked once on the morning of July 8 could have said RHEL was not vulnerable, hours before the same page flipped to list every RHEL kernel as affected. Trust any one of those and you file a vulnerable host as clear.
Rebootless Patching
GhostLock is the kind of bug rebootless patching exists for. The upstream change is available, but that does not protect a running system: the vendor has to backport it, you have to install the package, and the machine has to boot into the new kernel. On multi-tenant and container fleets, that last step can stretch a known local-root bug into weeks of residual exposure, and it is heaviest on exactly the hosts most at risk.
The change is a good rebootless-patch candidate: a small, self-contained correction in the locking path with no data-structure layout change and no persistent state to carry across. KernelCare ports the primary GhostLock fix, 3bfdc63936dd, into the running kernel. NB this is a kernel-only bug with no userspace-library component.
Live patches (KernelCare) release state as of 2026-07-10, 17:00 UTC.
Main feed:
- EL9 family: RHEL 9, AlmaLinux 9, Oracle Linux 9, Rocky Linux 9
- AlmaLinux 9 LTS and AlmaLinux 9 FIPS 9.6
- Ubuntu 24.04
- Proxmox VE 8
Testing feed:
- EL10 family: RHEL 10, AlmaLinux 10, Rocky Linux 10, Oracle Linux 10
- Debian 12
Vendor-fixed and released:
- Debian 13
Pending or not yet released:
- Amazon Linux 2023: built, not yet released
- Debian 11: coverage pending
- EL7: coverage pending
- EL6: low priority
KernelCare patch information references CVE-2026-43499 only; finding that CVE confirms GhostLock is patched. The follow-up change tracked as CVE-2026-53166 was reverted upstream because of a regression and is not required to verify coverage.
Apply from the testing feed once a K-tag is available:
kcarectl --update --prefix test
Apply from the production feed once promoted:
kcarectl --update
Confirm the GhostLock CVE mapping rather than trusting a build date:
kcarectl --info | grep kpatch-build-time # build dated 2026-07-08 or later
kcarectl --patch-info | grep 'CVE-2026-43499'
A build date alone proves nothing, because a kernel compiled after mid-April does not automatically carry the GhostLock fix. Verify the CVE mapping, the vendor erratum, the source, or the rebootless-patch status directly.
GhostLock turns a fifteen-year-old locking mistake into a failure of the local privilege boundary. For fleets that cannot absorb emergency reboots, a rebootless patch closes that boundary in the running kernel without draining nodes or interrupting workloads.
Timeline
| Date (2026) | Event |
|---|---|
| 04-18 | Reported to upstream (per Nebula Security bug list) |
| 04-20 | Fixed upstream, mainline 3bfdc63936dd |
| 05-04 | Backported (per Nebula Security bug list) |
| 05-21 | Red Hat CVE public date (BZ 2480453) |
| 06-30 | Google kernelCTF reward to VEGA / Nebula Security ($92,337) |
| 07-07 | Public disclosure (“IonStack part II: GhostLock”), full-chain PoC published, picked up by security press |
| 07-08 | KernelCare intake; trigger reproduced on Debian 11/12/13, EL7, EL10; Debian 13 confirmed already fixed |
References
- IonStack part II: GhostLock, Nebula Security, 2026-07-07: https://nebusec.ai/research/ionstack-part-2/
- Bug-list entry, CVE-2026-43499: https://nebusec.ai/buglist/CVE-2026-43499
- Public PoC, CyberMeowfia/IonStack/CVE-2026-43499: https://github.com/NebuSec/CyberMeowfia/tree/main/IonStack/CVE-2026-43499
- Upstream fix
3bfdc63936dd(“rtmutex: Use waiter::task instead of current in remove_waiter()”): https://git.kernel.org/linus/3bfdc63936dd4773109b7b8c280c0f3b5ae7d349 - Reverted follow-up change 74e144274af3 (CVE-2026-53166; later reverted upstream because of a regression): https://git.kernel.org/linus/74e144274af39935b0f410c0ee4d2b91c3730414
- Bug-introducing commit
8161239a8bcc(“rtmutex: Simplify PI algorithm and make highest prio task get lock”), contained in v2.6.39-rc1 - Red Hat CVE-2026-43499 (RHEL 6-10 kernel / kernel-rt listed Affected, severity Important, BZ 2480453): https://access.redhat.com/security/cve/cve-2026-43499
- CentOS Stream silent fixes: cs9
4e5a31ae1fa9, cs107bba8926cefe - Press: The Hacker News, “15-Year-Old GhostLock Flaw Enables Root…”: https://thehackernews.com/2026/07/15-year-old-ghostlock-flaw-enables-root.html