
Weaponized proof-of-concept for CVE-2026-43499 (GhostLock), a Linux kernel rtmutex bug enabling local privilege escalation. Includes per-distribution exploit chains, technical writeups, and reliability testing.
Weaponisation research for CVE-2026-43499 (ghostlock).
the rtmutex remove_water() proxy path bug that leaves a tasks pi_blocked_on dangling into its own popped kernel stack frame.
The bug class and original exploit strategy credit to nebusec (their write-up here)
everything in this repo is my own per-distribution work:
each kernel family needs materially different primitives and thats what makes this so interesting.
Ghostlocks trigger is completely unprivileged (three futexes, two threads and no namespaces). The process behind turning the dangling pointer into root is where each of the distros diverge, this comes down to frame geometry, mitigations, and what "controlled bytes at a known kernel address" even mean all change. This repo will collect chains per target family.
| Target | Chain | Staging | Status |
|---|---|---|---|
RHEL/CentOS 7 — 3.10.0-1160.102.1.el7 | el7/ — physmap-alias page + auxv painter + sched_setscheduler walk | root-in-namespace (privileged container) | working, 40/40 stress test on clean boots |
RHEL/CentOS 7 — 3.10.0-693.el7 | same chain, measured frame geometry | same | components validated 10/10; just pending a stress test |
see each subdirectorys WRITEUP.md for the full technical analysis, root cause, why the stock 6.x-era chain doesn't transfer,
the primitives findings, what i had built instead, measured frame geometries, and reliability related data.
where things get difficult - the walk validates the forged waiters ->lock against the lock it found through (BUG_ON(w->lock != lock) on 3.10), so you need fake structures in kernel-addressable memory at an address that you would know. this is what differs wildly per kernel (the 6.x-era CPU entry area trick that nebusec utilised, doesn't exist on 3.10, el7 randomises the direct base map, etc.). Each writeup documents its own answer.
the bug and trigger: you need no privileges, no user namespaces, nothing. any local user works.
each weaponisation states its own staging in its witeup. The el7 chain is staged from root-in-namespace (in practice: any RCE into a privileged container - this was validated from a MYSQL instance via its UDF plugin path, which is a very typical position to be in). The kernel side work after staging uses only:
/proc/self/pagemap with real PFNs (in-ns CAP_SYS_ADMIN)/proc/kcore (in-ns CAP_SYS_RAWIO on el7)/proc/kallsyms unamasked (kptr_restrict=0 or CAP_SYSLOG)None of those are the vulnerability itself, its just the staging conveniences that stand in for info leaks that I am yet to build.
On el7 specifically, a fully unprivileged chain is blocked for structural reasons (the 3.10 BUG_ON, no CEA, no static fake-lock pair in the kernels .data, pagemap PFN gating)
The el7 writeup has the full analysis and the research directions, mainly a head address info-leak primitive
panic_on_oops=1 hosts, a wrong walk will cause a panic and result in a dead machine, so treat it as a setting as part of your threat model when testingel7/
WRITEUP.md full technical writeup for el7 chain
ghostlock_el7.c single file poc for both tested kernels
3bfdc63936dd ("rtmutex: Use waiter::task instead of current in
remove_waiter()"); NPD follow-up 40a25d59e85b