
PD2229B的43499(ghostlock)可行性研究
| Element | Wert |
|---|---|
| Schwachstellentyp | Use-After-Free auf dem Stack im rt_mutex / futex-PI-Pfad |
| Eingeführt in Version | Linux 2.6.39-rc1 (Mai 2011, Commit 8161239a8bcc) |
| Behoben in Version | Hauptlinie 7.1 (Commit 3bfdc63936dd), stabile Zweige: 6.1.175 / 6.6.140 / 6.12.86 / 6.18.27 / 7.0.4 |
| Voraussetzungen | CONFIG_FUTEX_PI=y (standardmäßig in Mainstream-Kerneln aktiviert) |
| CVSS | 7.8 Hoch |
| Exploit-Stabilität | 97 % in der ursprünglichen NebuSec-Kette, Root in ca. 5 Sekunden |
| kernelCTF-Belohnung | 92.337 USD |
Betroffener Kernel-Bereich:
| Element | Wert |
|---|---|
| SoC | Qualcomm SM8475 (Snapdragon 8 Gen 1 Plus) |
| Kernel-Version | 5.10.233-gki-g6e61de9f5b58 #1 SMP PREEMPT (24. Nov. 2025) |
| Android-Version | 15 (OriginOS 5) |
| Build-Zeitpunkt | 25.11.2025 |
| Android-Patchlevel | 01.11.2025 |
CONFIG_FUTEX_PI | y ✅ |
CONFIG_UNMAP_KERNEL_AT_EL0 | y (KPTI aktiviert) |
kptr_restrict | erzwungen |
CONFIG_IO_URING | y ✅ (durch vmlinux-Symbole bestätigt, seccomp blockiert io_uring_setup nicht) |
1. KASLR-Umgehung → prefetch timing / PR_SET_MM_MAP auxv
2. UAF-Auslösung → Drei-Thread-PI-Abhängigkeits-Deadlock → FUTEX_CMP_REQUEUE_PI gibt -EDEADLK zurück
3. Stack-Recycling → PR_SET_MM_MAP kopiert auxv in den Waiter-Stackframe
4. rb_erase begrenztes Schreiben → Überschreiben von inet6_protos[IPPROTO_UDP]
5. CEA + ROP → Kontrollfluss-Übernahme
6. core_pattern-Flip → Root-Shell (97 % Erfolgsrate)
| Phase | Status | Beschreibung |
|---|---|---|
| 1. KASLR-Umgehung | ✅ Implementiert | perf_event_open + Callchain-Sampling-Seitenkanal (gleiche Methode wie bei der OPPO Find X6 Pro 5.15.149-Anpassung) |
| 2. UAF-Auslösung | ✅ Implementiert | Drei-Thread-PI-Deadlock erfolgreich, FUTEX_CMP_REQUEUE_PI gibt -EDEADLK zurück |
| 3. Stack-Recycling-Primitive | ❌ Architektonischer Fehlschlag | Stackframes aller bekannten Syscalls überlappen nicht mit dem Waiter (Details in Abschnitt 3) |
| 4. rb_erase begrenztes Schreiben | ❌ Blockiert | Voraussetzungen nicht erfüllt |
| 5. inet6_protos-Überschreiben | ❌ Nicht begonnen | Hängt von Phase 4 ab |
| 6. ROP / Kontrollfluss-Übernahme | ❌ Nicht begonnen | Hängt von Phase 5 ab |
| 7. Root-Shell | ❌ Nicht begonnen | Hängt von Phase 6 ab |
Gesamttiefe des futex-Pfads:
__arm64_sys_futex 0x90
+ do_futex 0xc0
+ futex_wait_requeue_pi 0x1b0
= 0x300
Waiter-Position = SYS_SP - 0x300 + 0x20 = SYS_SP - 0x2e0
pselect-Pfad:
core_sys_select Stackframe 0x1c0, stack_fds bei sp+0x50
Überdeckungsbereich: ab SYS_SP - 0x1c0 + 0x50 = SYS_SP - 0x170
Abstand zum Waiter (SYS_SP - 0x2e0) beträgt 0x170 (368 Bytes) → keine Überlappung
| # | Methode | Syscall | PD2229-Ergebnis | Hauptfehlergrund |
|---|---|---|---|---|
| 1 | stamp_prctl | PR_SET_MM_MAP | ❌ EPERM | Von Android hart blockiert |
| 2 | stamp_pselect | pselect6 (NFDS=320) | ❌ Keine Überlappung | Waiter liegt 120B unterhalb von fd_set |
| 3 | stamp_pselect | pselect6 (NFDS>336) | ❌ Heap-Allokation | kvmalloc-Pfad |
| 4 | stamp_socket | MCAST_JOIN_SOURCE_GROUP | ❌ Unzureichende Überdeckung | Schreibt nur lock-Feld |
| 5 | stamp_sendmsg | sendmsg | ❌ 80B vom Waiter entfernt | Stackframe 0x90 nicht tief genug |
| 6 | stamp_sendmmsg | sendmmsg | ❌ 112B vom Waiter entfernt | Stackframe unzureichend |
| 7 | stamp_recvmmsg | recvmmsg | ❌ Löscht task/lock | 0x1d0-Stackframe zerstört kritische Zeiger |
| 8 | stamp_process_vm | process_vm_writev | ❌ Keine Überlappung | Sub-Thread-Stack separat zugewiesen |
| 9 | stamp_keyctl | KEYCTL_INSTANTIATE_IOV | ❌ EOPNOTSUPP | Syscall nicht unterstützt + Stackframe 0x40 |
| 10 | stamp_tcp | TCP_ZEROCOPY_RECEIVE | ❌ Stackframe unzureichend | Geschätzte Tiefe nicht ausreichend |
| 11 | stamp_futex | FUTEX_CMP_REQUEUE_PI rekursiv | ❌ Logisch nicht machbar | Zerstört UAF-Fenster |
| 12 | binder ioctl | BINDER_WRITE_READ | ❌ EACCES | Shell hat keine /dev/binder-Berechtigung |
| 13 | poll | poll | ❌ Heap-Allokation | pollfd liegt auf dem Heap |
| 14 | epoll_wait | epoll_wait | ❌ Frame zu flach | Stackframe 0xE0 |
| 15 | sched_setattr | sched_setattr | ❌ Tiefe unzureichend | Stackframe 0xb0 |
| 16 | timerfd_settime | timerfd_settime | ❌ Kein Stack-Kopieren | Kein großer Stack-Puffer |
| 17 | io_uring_register | IORING_REGISTER_* | ❌ Doppelter Fehlschlag | ①Stackframe nur 0xF0, copy_from_user-Ziel fest bei sp+0x8 (424 Bytes Differenz zum Waiter bei sp+0x1D0); ②Obwohl io_uring_setup nicht von seccomp blockiert wird (gibt EFAULT statt ENOSYS zurück), passt das Stack-Layout nicht |
17/17 alle fehlgeschlagen.
Das vom SM8475-5.10-GKI-Compiler (PGO + LTO + BOLT) auf PD2229 erzeugte Stack-Layout führt dazu, dass stack_fds von core_sys_select und rt_mutex_waiter von futex_wait_requeue_pi architektonisch nicht überlappen. Dies ist eine objektive, vom Compiler bestimmte Tatsache und kein Problem der Exploit-Technik.
Das JoinChang-Repository stellt klar: "The pselect stack overlay only works when the freed rt_mutex_waiter lands within the user-controllable region of the stack_fds buffer" — PD2229 erfüllt diese Bedingung nicht.
PR_SET_MM_MAP kopiert auxv auf den Kernel-StackPR_SET_MM_MAP wird auf Android mit EPERM blockiertPSELECT_SHIFT = -2