
PD2229B的43499(ghostlock)可行性研究
| Voce | Valore |
|---|---|
| Tipo di vulnerabilità | Use-After-Free sullo stack nel percorso rt_mutex / futex PI |
| Versione di introduzione | Linux 2.6.39-rc1 (maggio 2011, commit 8161239a8bcc) |
| Versione corretta | Mainline 7.1 (commit 3bfdc63936dd), rami stabili: 6.1.175 / 6.6.140 / 6.12.86 / 6.18.27 / 7.0.4 |
| Prerequisito | CONFIG_FUTEX_PI=y (abilitato di default nei kernel mainstream) |
| CVSS | 7.8 High |
| Stabilità dello sfruttamento | 97% nella catena originale NebuSec, root in circa 5 secondi |
| Ricompensa kernelCTF | $92.337 USD |
Intervallo di kernel interessati:
| Voce | Valore |
|---|---|
| SoC | Qualcomm SM8475 (Snapdragon 8 Gen 1 Plus) |
| Versione kernel | 5.10.233-gki-g6e61de9f5b58 #1 SMP PREEMPT (24 nov 2025) |
| Versione Android | 15 (OriginOS 5) |
| Data di compilazione | 25/11/2025 |
| Patch Android | 01/11/2025 |
CONFIG_FUTEX_PI | y ✅ |
CONFIG_UNMAP_KERNEL_AT_EL0 | y (KPTI attivo) |
kptr_restrict | enforced |
CONFIG_IO_URING | y ✅ (confermato dal simbolo vmlinux e seccomp non intercetta io_uring_setup) |
1. Bypass KASLR → prefetch timing / PR_SET_MM_MAP auxv
2. Trigger UAF → deadlock di dipendenza PI a tre thread → FUTEX_CMP_REQUEUE_PI restituisce -EDEADLK
3. Riciclo stack → PR_SET_MM_MAP copia auxv nel frame dello stack del waiter
4. Scrittura limitata rb_erase → sovrascrive inet6_protos[IPPROTO_UDP]
5. CEA + ROP → dirottamento del flusso di controllo
6. Inversione core_pattern → shell root (tasso di successo 97%)
| Fase | Stato | Descrizione |
|---|---|---|
| 1. Bypass KASLR | ✅ Implementato | Canale laterale perf_event_open + campionamento callchain (stesso metodo di adattamento di OPPO Find X6 Pro 5.15.149) |
| 2. Trigger UAF | ✅ Implementato | Deadlock PI a tre thread riuscito, FUTEX_CMP_REQUEUE_PI restituisce -EDEADLK |
| 3. Primitiva di riciclo stack | ❌ Fallimento architetturale | I frame dello stack di tutte le syscall note non si sovrappongono al waiter (vedi Sezione 3) |
| 4. Scrittura limitata rb_erase | ❌ Bloccata | Prerequisiti non soddisfatti |
| 5. Sovrascrittura inet6_protos | ❌ Non iniziata | Dipende dalla fase 4 |
| 6. ROP / dirottamento del flusso di controllo | ❌ Non iniziata | Dipende dalla fase 5 |
| 7. Shell root | ❌ Non iniziata | Dipende dalla fase 6 |
Profondità totale del percorso futex:
__arm64_sys_futex 0x90
+ do_futex 0xc0
+ futex_wait_requeue_pi 0x1b0
= 0x300
Posizione waiter = SYS_SP - 0x300 + 0x20 = SYS_SP - 0x2e0
Percorso pselect:
stack frame core_sys_select 0x1c0, stack_fds a sp+0x50
Intervallo di copertura: a partire da SYS_SP - 0x1c0 + 0x50 = SYS_SP - 0x170
Differenza dal waiter (SYS_SP - 0x2e0) di 0x170 (368 byte) → nessuna sovrapposizione
| # | Metodo | Syscall | Risultato su PD2229 | Motivo principale del fallimento |
|---|---|---|---|---|
| 1 | stamp_prctl | PR_SET_MM_MAP | ❌ EPERM | Intercettazione rigida Android |
| 2 | stamp_pselect | pselect6 (NFDS=320) | ❌ Nessuna sovrapposizione | Waiter 120B sotto fd_set |
| 3 | stamp_pselect | pselect6 (NFDS>336) | ❌ Allocazione heap | Percorso kvmalloc |
| 4 | stamp_socket | MCAST_JOIN_SOURCE_GROUP | ❌ Copertura insufficiente | Scrive solo il campo lock |
| 5 | stamp_sendmsg | sendmsg | ❌ A 80B dal waiter | Profondità stack frame 0x90 insufficiente |
| 6 | stamp_sendmmsg | sendmmsg | ❌ A 112B dal waiter | Stack frame insufficiente |
| 7 | stamp_recvmmsg | recvmmsg | ❌ Azzera task/lock | Lo stack frame 0x1d0 danneggia puntatori critici |
| 8 | stamp_process_vm | process_vm_writev | ❌ Nessuna sovrapposizione | Stack del thread figlio allocato separatamente |
| 9 | stamp_keyctl | KEYCTL_INSTANTIATE_IOV | ❌ EOPNOTSUPP | Syscall non supportata + stack frame 0x40 |
| 10 | stamp_tcp | TCP_ZEROCOPY_RECEIVE | ❌ Stack frame insufficiente | Profondità stimata non sufficiente |
| 11 | stamp_futex | FUTEX_CMP_REQUEUE_PI ricorsivo | ❌ Logicamente non fattibile | Distrugge la finestra UAF |
| 12 | binder ioctl | BINDER_WRITE_READ | ❌ EACCES | La shell non ha permessi su /dev/binder |
| 13 | poll | poll | ❌ Allocazione heap | pollfd sull'heap |
| 14 | epoll_wait | epoll_wait | ❌ Frame troppo superficiale | Stack frame 0xE0 |
| 15 | sched_setattr | sched_setattr | ❌ Profondità insufficiente | Stack frame 0xb0 |
| 16 | timerfd_settime | timerfd_settime | ❌ Nessuna copia stack | Nessun buffer stack di grandi dimensioni |
| 17 | io_uring_register | IORING_REGISTER_* | ❌ Doppio fallimento | ①Stack frame solo 0xF0, destinazione copy_from_user fissa a sp+0x8 (differenza di 424 byte dal sp+0x1D0 del waiter); ②sebbene io_uring_setup non sia intercettato da seccomp (restituisce EFAULT invece di ENOSYS), il layout dello stack non corrisponde |
17/17 tutti falliti.
Il layout dello stack prodotto dal compilatore GKI 5.10 di SM8475 su PD2229 (PGO + LTO + BOLT) fa sì che stack_fds di core_sys_select e rt_mutex_waiter di futex_wait_requeue_pi non si sovrappongano architetturalmente. Questo è un fatto oggettivo determinato dal compilatore, non un problema di tecnica di sfruttamento.
Il repository JoinChang afferma esplicitamente: "The pselect stack overlay only works when the freed rt_mutex_waiter lands within the user-controllable region of the stack_fds buffer" — PD2229 non soddisfa questa condizione.
PR_SET_MM_MAP copia auxv nello stack del kernelPR_SET_MM_MAP intercettato con EPERM su AndroidPSELECT_SHIFT = -2