
PD2229B的43499(ghostlock)可行性研究
| Elemento | Valor |
|---|---|
| Tipo de vulnerabilidad | Use-After-Free en la pila en la ruta rt_mutex / futex PI |
| Versión introducida | Linux 2.6.39-rc1 (mayo de 2011, commit 8161239a8bcc) |
| Versión corregida | mainline 7.1 (commit 3bfdc63936dd), ramas estables: 6.1.175 / 6.6.140 / 6.12.86 / 6.18.27 / 7.0.4 |
| Requisito previo | CONFIG_FUTEX_PI=y (habilitado por defecto en kernels principales) |
| CVSS | 7.8 High |
| Estabilidad de explotación | Cadena original de NebuSec 97%, root en ~5 segundos |
| Recompensa kernelCTF | $92,337 USD |
Rango de kernels afectados:
| Elemento | Valor |
|---|---|
| SoC | Qualcomm SM8475 (Snapdragon 8 Gen 1 Plus) |
| Versión del kernel | 5.10.233-gki-g6e61de9f5b58 #1 SMP PREEMPT (24 nov 2025) |
| Versión de Android | 15 (OriginOS 5) |
| Fecha de compilación | 2025/11/25 |
| Parche de Android | 2025/11/01 |
CONFIG_FUTEX_PI | y ✅ |
CONFIG_UNMAP_KERNEL_AT_EL0 | y (KPTI habilitado) |
kptr_restrict | enforced |
CONFIG_IO_URING | y ✅ (confirmado por símbolos de vmlinux, y seccomp no bloquea io_uring_setup) |
1. Bypass de KASLR → prefetch timing / PR_SET_MM_MAP auxv
2. Disparo de UAF → deadlock de dependencia PI de tres hilos → FUTEX_CMP_REQUEUE_PI devuelve -EDEADLK
3. Reciclaje de pila → PR_SET_MM_MAP copia auxv al marco de pila del waiter
4. Escritura restringida rb_erase → sobrescribe inet6_protos[IPPROTO_UDP]
5. CEA + ROP → secuestro del flujo de control
6. Cambio de core_pattern → shell root (97% de éxito)
| Etapa | Estado | Descripción |
|---|---|---|
| 1. Bypass de KASLR | ✅ Implementado | Canal lateral perf_event_open + muestreo de callchain (mismo método de adaptación que OPPO Find X6 Pro 5.15.149) |
| 2. Disparo de UAF | ✅ Implementado | Deadlock PI de tres hilos exitoso, FUTEX_CMP_REQUEUE_PI devuelve -EDEADLK |
| 3. Primitiva de reciclaje de pila | ❌ Fallo arquitectónico | Los marcos de pila de todas las syscalls conocidas no se superponen con el waiter (ver sección 3) |
| 4. Escritura restringida rb_erase | ❌ Bloqueado | Requisito previo no cumplido |
| 5. Sobrescritura de inet6_protos | ❌ No iniciado | Depende de la etapa 4 |
| 6. ROP / secuestro del flujo de control | ❌ No iniciado | Depende de la etapa 5 |
| 7. Shell root | ❌ No iniciado | Depende de la etapa 6 |
Profundidad total de la ruta futex:
__arm64_sys_futex 0x90
+ do_futex 0xc0
+ futex_wait_requeue_pi 0x1b0
= 0x300
Posición del waiter = SYS_SP - 0x300 + 0x20 = SYS_SP - 0x2e0
Ruta pselect:
marco de pila core_sys_select 0x1c0, stack_fds en sp+0x50
Rango cubierto: SYS_SP - 0x1c0 + 0x50 = desde SYS_SP - 0x170
Diferencia con waiter (SYS_SP - 0x2e0) de 0x170 (368 bytes) → sin superposición
| # | Método | Syscall | Resultado en PD2229 | Razón principal del fallo |
|---|---|---|---|---|
| 1 | stamp_prctl | PR_SET_MM_MAP | ❌ EPERM | Bloqueo duro de Android |
| 2 | stamp_pselect | pselect6 (NFDS=320) | ❌ Sin superposición | waiter está 120B por debajo de fd_set |
| 3 | stamp_pselect | pselect6 (NFDS>336) | ❌ Asignación en heap | Ruta kvmalloc |
| 4 | stamp_socket | MCAST_JOIN_SOURCE_GROUP | ❌ Cobertura insuficiente | Solo escribe el campo lock |
| 5 | stamp_sendmsg | sendmsg | ❌ A 80B del waiter | Profundidad del marco 0x90 insuficiente |
| 6 | stamp_sendmmsg | sendmmsg | ❌ A 112B del waiter | Marco insuficiente |
| 7 | stamp_recvmmsg | recvmmsg | ❌ Borra task/lock | El marco 0x1d0 corrompe punteros críticos |
| 8 | stamp_process_vm | process_vm_writev | ❌ Sin superposición | Pila del hilo hijo asignada por separado |
| 9 | stamp_keyctl | KEYCTL_INSTANTIATE_IOV | ❌ EOPNOTSUPP | Syscall no soportada + marco 0x40 |
| 10 | stamp_tcp | TCP_ZEROCOPY_RECEIVE | ❌ Marco insuficiente | Profundidad estimada insuficiente |
| 11 | stamp_futex | FUTEX_CMP_REQUEUE_PI recursivo | ❌ Lógicamente inviable | Corrompe la ventana de UAF |
| 12 | binder ioctl | BINDER_WRITE_READ | ❌ EACCES | shell sin permiso en /dev/binder |
| 13 | poll | poll | ❌ Asignación en heap | pollfd en el heap |
| 14 | epoll_wait | epoll_wait | ❌ Marco demasiado superficial | Marco 0xE0 |
| 15 | sched_setattr | sched_setattr | ❌ Profundidad insuficiente | Marco 0xb0 |
| 16 | timerfd_settime | timerfd_settime | ❌ Sin copia en pila | Sin buffer grande en pila |
| 17 | io_uring_register | IORING_REGISTER_* | ❌ Doble fallo | ①Marco de solo 0xF0, el destino de copy_from_user fijo en sp+0x8 (diferencia de 424 bytes con sp+0x1D0 del waiter); ②aunque io_uring_setup no está bloqueado por seccomp (devuelve EFAULT en lugar de ENOSYS), el diseño de pila no coincide |
17/17 fallaron todos.
El diseño de pila generado por el compilador del SM8475 5.10 GKI de PD2229 (PGO + LTO + BOLT) hace que stack_fds de core_sys_select y rt_mutex_waiter de futex_wait_requeue_pi no se superpongan arquitectónicamente. Este es un hecho objetivo determinado por el compilador, no un problema de técnica de explotación.
El repositorio de JoinChang establece claramente: "The pselect stack overlay only works when the freed rt_mutex_waiter lands within the user-controllable region of the stack_fds buffer" — PD2229 no cumple esta condición.
PR_SET_MM_MAP copia auxv a la pila del kernelPR_SET_MM_MAP bloqueado con EPERM en AndroidPSELECT_SHIFT = -2