
# GhostLock (CVE-2026-43499) exploit del kernel per dispositivi Android con bootloader bloccato
Exploit del kernel per dispositivi Android con bootloader bloccato. Ottiene root temporaneo + installazione di KernelSU senza sbloccare il bootloader o modificare l'immagine di boot. Rilevamento automatico a runtime della versione del kernel con tabella degli offset multi-dispositivo.
CVE-2026-43499 — Use-After-Free in Futex PI (Priority Inheritance)
Interessa il kernel Linux 5.7 ~ 7.1. Corretto nelle versioni stabili 6.1.175, 6.6.140, 6.12.86. La maggior parte dei dispositivi Android rimane non corretta a settembre 2026.
La syscall pselect6 copia i dati di fd_set sullo stack del kernel. Se combinato con il meccanismo dei waiter futex PI, un frame dello stack liberato può essere riallocato come struttura rt_mutex_waiter. Il ribilanciamento dell'rb-tree durante la traversata della catena PI scrive quindi valori controllati su indirizzi arbitrari del kernel.
| Dispositivo | SoC | Kernel | Ramo GKI | SHIFT |
|---|---|---|---|---|
| OnePlus Ace 6T (PLR110) | SM8845 | 6.12.38 | android16-5 | 0 |
| OnePlus 15 (CPH2745/2747/2749) | SM8850 | 6.12.23 | android16-5 | 0 |
| OnePlus 15 (PLK110) | SM8850 | 6.12.58 | android16-6 | 0 |
| Xiaomi 17 (pudding) | SM8850 | 6.12.23 / 6.12.69 | android16-5 / android16-6 | 0 |
| OnePlus 13 (IN2060) | SM8750 | 6.6.89 | android15-8 | -2 |
| OPPO Pad 4 Pro | SM8750 | 6.6.89 | android15-8 | -2 |
| Dispositivo | SoC | Kernel | Note |
|---|---|---|---|
| OnePlus 15T (PLZ110) | SM8845 | 6.12.38 | Stesso kernel dell'Ace 6T |
| OPPO Reno10 Pro+ (CPH2521) | SM8475 | 5.10.236 | waiter compatto 5.10, waiter word=0 |
| Sony Xperia 1 IV (nagara) | SM8450 | 5.10.218 | waiter compatto 5.10, waiter word=0 |
| OPPO Find X9 Pro (PLG110) | D9400 | 6.12.23 | MediaTek, android16-5 |
| Vivo X200 Ultra (V2454A) | SM8750 | 6.6.89 | ashmem C, hook tradizionali |
| Vivo X Fold3 Pro (PD2337) | SM8650 | 6.1.124 | waiter compatto 6.1, waiter word=3 |
| Vivo T4 | SM8650 | 6.1.145 | waiter compatto 6.1, waiter word=3 |
La sovrapposizione dello stack di pselect richiede che il rt_mutex_waiter liberato finisca all'interno della regione stack_fds controllabile dall'utente (word 0–14). Il punto in cui finisce è determinato dai profili PGO/LTO del compilatore, non dalla versione del kernel. Vedi Layout dello stack.
| Dispositivo | SoC | Kernel | Causa principale |
|---|---|---|---|
| OPPO Find X9 Ultra | SM8750 | 6.12.58 | PGO elimina do_futex → waiter word=14 |
| OnePlus 15 (PLK110) | SM8850 | 6.12.69 | PGO inlina do_futex → waiter word=20 |
| OnePlus 12 | SM8650 | 6.1.141 | PGO inlina do_futex → waiter word=13/19 |
| OnePlus 13R / Ace 5 | SM8650 | 6.1.x | OPLUS 6.1: waiter word=13 |
| realme RMX5070 | SM6650 | 6.1.141 | OPLUS 6.1: waiter word=13 |
| OPPO Pad 5 (OPD2502) | MT6878 | 6.1.134 | OPLUS 6.1: waiter word=13 |
| Motorola Edge 60 Fusion | MT6878 | 6.1.145 | Non-OPLUS 6.1: stesso risultato |
| iQOO Neo 10 CN | SM8650 | 6.1.84 | frame do_futex 0xD0 → waiter word=-11 |
| OPPO PKW110 | — | 5.15.180 | frame do_futex 0x140 → waiter word=-29 |
| iQOO Z9 5G | — | 5.15.178 | frame do_futex troppo grande |
| CPH2763 (OPPO) | — | 6.1.115 | OPLUS 6.1: PGO inlinato, waiter word=24 |
| iQOO 12 | SM8650 | 6.1.145 | 6.1: waiter word=9, task/lock nell'area azzerata |
Nota sulla fattibilità su 6.1: i kernel OPLUS 6.1 sono costantemente non fattibili a causa dell'inlining di
do_futexda parte di PGO. Tuttavia, alcuni kernel 6.1 non OPLUS (vivo) mantengono la catena di chiamate standard e sono fattibili (vivo T4, X Fold3 Pro). La fattibilità deve essere verificata per singolo dispositivo.
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
→ configfs r/w → pipe physrw (1-byte precise kernel r/w)
→ SELinux enforcing = 0 (single byte, no policycap corruption)
→ UMH: inject work_struct into system_unbound_wq
→ root script → ksud late-load → KSU installed
Disponibile su: OnePlus 13, OPPO Pad 4 Pro, dispositivi con ashmem 5.10/6.1 C. Non disponibile su ashmem Rust (6.12 GKI) — miscdevice allocato nell'heap.
Write 1 (mode=1) → SELinux enforcing = 0 (8-byte write, corrupts adjacent bytes)
Write 2 (mode=2) → task->cred = init_cred (uid=0, all capabilities)
Root shell → ksud late-load → KSU → SELinux policy fix
Dopo W1+W2, l'exploit modifica il campo di configurazione del binario della policy SELinux (|= 0xC0000000 per ANDROID_NETLINK_ROUTE + GETNEIGH) e ricarica tramite /sys/fs/selinux/load per ripristinare la connettività di rete.
App (seccomp) → Write 1 → mini-adb TCP → adb shell: full exploit → root
Il launcher all'avvio è fornito dalla app separata GhostLock Anchor.
Con NFDS=320, core_sys_select alloca un buffer stack_fds di 256 byte sullo stack del kernel:
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 inserisce falsi campi waiter (task, lock) nelle bitmap di input fd_set. Per il waiter annidato 6.12 (14 word): word massima del waiter fattibile = 3. Per il waiter compatto 5.10/6.1 (10 word): word massima del waiter fattibile = 7.
La posizione del waiter dipende dalla profondità della catena di chiamate:
| Pattern | Catena di chiamate | Fattibile |
|---|---|---|
| android16-5 (6.12) | sys_futex → do_futex → fwrpi | ✅ waiter word=2 |
| android16-6 (6.12.58) | sys_futex → do_futex → fwrpi | ✅ waiter word=2 |
| android16-6 (6.12.69 OPLUS) | sys_futex → fwrpi (PGO inlined) | ❌ waiter word=20 |
| android16-6 (X9 Ultra) | sys_futex → fwrpi (PGO inlined) | ❌ waiter word=14 |
| android15-8 (6.6) | sys_futex → do_futex → fwrpi | ✅ waiter word=2 (SHIFT=-2) |
| vivo 6.1 | sys_futex → do_futex → fwrpi | ✅ waiter word=3 |
| OPLUS 6.1 | sys_futex → fwrpi (PGO inlined) | ❌ waiter word=13+ |
| 5.10 OPLUS | sys_futex → do_futex → fwrpi | ✅ waiter word=0 |
Tutte le scritture nel kernel usano l'alias della mappa lineare. Il bootloader sceglie kernel_phys_load, che varia per SoC:
| SoC | kernel_phys_load |
|---|---|
| SM8845 (Ace 6T, 15T) | 0xa8000000 |
| SM8750 (OnePlus 13, OPPO Pad 4 Pro) | 0xa8000000 |
| SM8650 (vivo T4, X Fold3 Pro) | 0xa8000000 |
| SM8850 (OnePlus 15, Xiaomi 17) | 0xc7800000 |
Un valore errato fallisce silenziosamente. Leggilo su un'unità con root:
su -c 'grep -i "Kernel code" /proc/iomem' # c7810000-... → 0xc7800000
Esegui l'override a runtime: KPHYS=0xc7800000 /data/local/tmp/a/e
/data/local/tmp/a/e # Default (shift=0)
PSELECT_SHIFT=-2 /data/local/tmp/a/e # OnePlus 13 (6.6)