
GhostLock (CVE-2026-43499) adattatore per kernel Android 4.19.152-perf+
Exploit del kernel per dispositivi OnePlus/OPPO/realme con bootloader bloccato. Ottiene la root + installazione di KernelSU senza sbloccare il bootloader o modificare l'immagine di boot. Rilevamento automatico a runtime della versione del kernel con tabella di offset multi-dispositivo.
CVE-2026-43499 — Futex PI (Priority Inheritance) Use-After-Free
Colpisce il kernel Linux 2.6.39 ~ 7.1. Corretto nel mainline 7.1 (commit 3bfdc63936dd). Android GKI 6.12.x rimane vulnerabile.
La syscall pselect6 copia i dati fd_set sullo stack del kernel. Quando combinata con il meccanismo futex PI waiter, un frame di stack liberato può essere riutilizzato come struttura rt_mutex_waiter. Il ribilanciamento dell'albero rb durante la scansione della catena PI scrive quindi valori controllati a indirizzi arbitrari del kernel.
| Dispositivo | SoC | Kernel | Stato |
|---|---|---|---|
| OnePlus Ace 6T (PLR110) | SM8845 | 6.12.38-...-ab14275539 | Funzionante |
| OnePlus Ace 6T (PLR110) | SM8845 | 6.12.38-...-ab14552068 | Funzionante |
| OnePlus 15 (CPH2749) | SM8850 | 6.12.23-...-ab14541642 | Funzionante |
| Xiaomi 17 (pudding) | SM8850 | 6.12.23-...-abogki463945075 | Funzionante |
| Xiaomi 17 (pudding) | SM8850 | 6.12.69-...-abogki514973465 | Funzionante (aggiornamento di agosto 2026) |
| OnePlus 13 (IN2060) | SM8750 | 6.6.89-...-abogki446052083 | Funzionante (PSELECT_SHIFT=-2) |
| OPPO Pad 4 Pro | SM8750 | 6.6.89-...-ab14358676 | Funzionante (PSELECT_SHIFT=-2) |
| Dispositivo | SoC | Kernel | Note |
|---|---|---|---|
| OnePlus 15T (PLZ110) | SM8845 | 6.12.38-...-ab14552068 | Stesso kernel di Ace 6T. QEMU ha verificato SP diff=-64. |
L'overlay dello stack pselect funziona solo quando il rt_mutex_waiter liberato ricade nella regione controllabile dall'utente del buffer stack_fds. La posizione del waiter è determinata dall'output del compilatore (PGO + LTO), non dalla versione del kernel. Vedere Layout dello Stack per i dettagli.
| Dispositivo | SoC | Kernel | Motivo |
|---|---|---|---|
| OPPO Find X9 Ultra | SM8750 | 6.12.58-android16-6 | PGO elimina il frame do_futex → SP diff=+32, waiter word=14. Non esiste uno shift sicuro. |
| OPPO Find X7 | — | 6.1.157 | 6.1 GKI: waiter a word 13 (tutti i dispositivi 6.1 OPLUS/GKI) |
| realme RMX5070 | SM6650 | 6.1.141 | 6.1 GKI: waiter a word 13 |
| realme RMX3852 | SM8635 | 6.1.141 | Stesso ramo 6.1 di RMX5070 |
| OnePlus 13R / Ace 5 | SM8650 | 6.1.x | Stesso ramo 6.1 |
| OnePlus 12 | SM8650 | 6.1.141 | 6.1 GKI: do_futex inline con PGO, waiter word=13/19 |
| OPPO Pad 5 (OPD2502) | MT6878 | 6.1.134 | Stesso ramo 6.1 |
| OPPO PKW110 | — | 5.15.180 | Frame do_futex 0x140 (4,5x normale) → waiter word=-29, irraggiungibile |
| Motorola Edge 60 Fusion | MT6878 | 6.1.145 | 6.1 GKI: waiter a word 13 (non OPLUS, stesso risultato) |
| iQOO Z9 5G | — | 5.15.178 | Frame do_futex troppo grande, waiter irraggiungibile. Non è un dispositivo OPLUS (vivo). |
Due percorsi di root, selezionati automaticamente in base alle capacità del dispositivo:
Richiede off_ashmem_misc_fops != 0 (ashmem C con miscdevice statico in BSS).
PI write (mode=4) → redirect miscdevice fops to fake fops (via W0 pi_tree)
configfs r/w established
→ pipe physrw (1-byte precise kernel r/w)
→ SELinux enforcing = 0 (single byte, no policycap corruption)
→ UMH: inject work_struct into system_unbound_wq
kernel executes /data/local/tmp/a/e --umh as UID 0
→ root script → ksud late-load → KSU installed
Vantaggi rispetto al Percorso B:
selinux_state.policycap (risolve i problemi di rete su OnePlus 13)Attualmente disponibile su: OnePlus 13 (kernel 6.6, ashmem C). Non disponibile su dispositivi con ashmem Rust (6.12 GKI) — il miscdevice è allocato sullo heap, l'indirizzo non è prevedibile in fase di compilazione.
Usato quando gli offset UMH o i misc_fops dell'ashmem C non sono disponibili.
Write 1 (mode=1) → SELinux enforcing = 0
(low byte of kernel ptr = 0x00, 8-byte write)
Write 2 (mode=2) → task->cred = init_cred
(uid=0, all capabilities)
Root shell → ksud late-load (KernelSU LKM)
→ su -c load_policy (fix SELinux policycap)
→ dynamic manager registration
App (seccomp) → Write 1 (no perf needed)
→ mini-adb connect TCP (port from /data/local/tmp/a/adb_port, default 5555)
→ adb shell: full exploit (perf works, no seccomp)
→ root → KSU → network fix
BOOT_COMPLETED → BootCompletedReceiver
├─ su available → skip (soft reboot / already rooted)
└─ no root → GhostlockService → setsid exploit --bootstrap
Con NFDS=320, core_sys_select del kernel alloca un buffer stack_fds di 256 byte:
stack_fds: 0 5 10 14 | 15 20 25 29
├─in─┤─out─┤─ex──┤ ├res_in┤res_out┤res_ex┤
◄── USER CONTROLLED ──►│◄── KERNEL ZEROED ──►
L'exploit scrive campi fittizi del waiter (task, lock) nelle bitmap di input fd_set. Perché funzioni, i campi task e lock del waiter devono ricadere nella zona controllabile (word 0-14).
Ace 6T ✅ (waiter at word 2):
░░████████████████░░│░░░░░░░░░░░░░░░░░░
▲waiter t l │
task/lock controllable
RMX5070 ❌ (waiter at word 13):
░░░░░░░░░░░░░████│██████████████░░░░░░
▲ │ t l
waiter task/lock ZEROED
Regola di fattibilità: waiter word + 11 (offset di lock in rt_waiter_node) deve essere ≤ 14. La word massima di waiter fattibile è 3.
La posizione del waiter è determinata dal layout dei frame di stack del compilatore (profili di ottimizzazione PGO + LTO + BOLT), che varia in base al ramo del SoC. La stessa versione del kernel può avere layout diversi su SoC diversi.
Tutte le scritture sul kernel passano attraverso l'alias linear-map dell'immagine:
data_addr(x) = PAGE_OFFSET + (kernel_phys_load - PHYS_OFFSET) + (x - KIMAGE_TEXT_BASE)
Il bootloader sceglie kernel_phys_load, quindi varia in base al SoC e non è presente in boot.img né nel DT. Campo per-dispositivo in struct kernel_offsets; 0 = usa il valore predefinito di target.h.
| SoC | kernel_phys_load |
|---|---|
| SM8845 (Ace 6T, 15T) | 0xa8000000 |
| SM8750 (OnePlus 13, OPPO Pad 4 Pro) | 0xa8000000 |
| SM8850 (OnePlus 15, Xiaomi 17) | 0xc7800000 |