
Proof-of-concept per CVE-2026-64788, una use-after-free nell'estensione del kernel IOGPUFamily su iOS 26.6, che dimostra lo sfruttamento tramite la creazione di texture Metal e heap spraying.
Componente: estensione kernel IOGPUFamily (com.apple.iokit.IOGPUFamily)
Interessati: iOS / iPadOS 26.6 (23G71) e versioni precedenti
Corretto in: iOS / iPadOS 26.6.1 (23G83)
Tipo: Use-After-Free in IOGPUDevice::create_resource_iosurface
Impatto: corruzione della memoria del kernel; dereferenziazione UAF confermata su A14 (iPhone 12)
Scoperto da: f00l (@PPPF00L), 3ndy1 (@_3ndy1), Minghao Lin (@Y1nkoc), 云散花折, Arjanit Isufi
(secondo Apple Security Advisory — iOS 26.6.1)
IOGPUDevice::create_resource_iosurface alloca un oggetto IOGPUSysMemory (~0x100 byte, zona ) e lo registra nella tabella delle risorse IOSurface del dispositivo. Prima di restituire il controllo, un controllo di overflow delle dimensioni viene attivato tramite . Il percorso di overflow dirama verso un ritorno di errore , lasciando una voce attiva nella tabella delle risorse che punta a memoria liberata.
kalloc.256ADDS width+height → b.hscreate_resource_iosurface:
kalloc(0x100) → obj ; IOGPUSysMemory allocato
table[new_id] = obj ; registrato con un riferimento
ADDS w_result, w_width, w_height
b.hs error_path ; ← overflow: salta qui
error_path:
; oggetto NON rilasciato, voce della tabella NON cancellata
return kIOReturnInvalid
La voce stantia nella tabella persiste finché lo stesso ID di risorsa non viene riutilizzato o il dispositivo non viene chiuso.
IOGPUDevice::set_resource_purgeable(id) cerca l'ID stantio tramite get_resource_by_id(), trova la voce pendente e vi accede in modo non virtuale:
| Offset | Operazione | Descrizione |
|---|---|---|
+0x010c | ldaddl w9(-4), w8, [obj+0x24] | Decremento atomico di [obj+0x24]; vecchio valore → w8 |
+0x0128 | cbz w8, skip; ldr x1, [obj+0x28] | Se il vecchio [+0x24] != 0: carica [obj+0x28] come argomento per IOGPUMemory::setAllocation |
+0x0134 | ldr x0, [obj+0x10] | Carica [obj+0x10] come argomento IOCommandGate; cbz → skip se 0 |
Il PoC attiva la UAF utilizzando newTextureWithDescriptor:iosurface:plane: di Metal con dimensioni di overflow appositamente costruite. Prima della dereferenziazione UAF:
kalloc.256 liberato[+0x10]=0, [+0x24]=0, [+0x28]=0 → Call2 e Call3 vengono saltate in sicurezzaRilevamento del trigger: set_resource_purgeable su una risorsa inesistente restituisce 0xe00002c2. Dopo che la UAF + lo spray reclamano lo slot, la stessa chiamata restituisce 0xe0002be (risorsa trovata, Call1 attivata) — confermando che la voce stantia viene elaborata con i nostri dati spray.
La segregazione delle zone in iOS 26 colloca gli oggetti IOGPUSysMemory liberati nuovamente in una lista libera di zona type-stable. Sia [obj+0x10] (IOMemoryDescriptor) che [obj+0x18] (IOGPUDevice) mantengono conteggi di retain esterni e rimangono attivi dopo che l'oggetto è stato liberato. Di conseguenza, completeMemory() viene sempre eseguito su dati ivar validi — la dereferenziazione UAF è confermata ma una primitiva di lettura/scrittura del kernel tramite questo solo percorso è bloccata su iOS 26 senza una primitiva secondaria per rompere la segregazione delle zone.
clang -arch arm64 -framework Metal -framework IOSurface \
-framework IOKit -framework Foundation \
-o poc poc/poc_iogpu_uaf.m
Oppure apri in Xcode, imposta un team di firma valido ed esegui sul dispositivo.
| Data | Evento |
|---|---|
| 2026-08-17 | iOS 26.6.1 rilasciato con la correzione |
| 2026-08-17 | Crediti Apple pubblicati nell'advisory di sicurezza |