
Divulgazione pubblica per CVE-2026-43655 AppleM2ScalerCSCDriver use-after-free
Divulgazione tecnica pubblica per CVE-2026-43655, un use-after-free di AppleM2ScalerCSCDriver / IOSurfaceAccelerator raggiungibile dal sandbox predefinito delle app iOS senza autorizzazioni speciali.
Apple ha risolto questo problema in iOS 26.5 / iPadOS 26.5 / macOS Tahoe 26.5. Questo repository contiene il codice sorgente della proof-of-concept in Objective-C, le autorizzazioni minime, un IPA compilato e la documentazione tecnica necessaria per comprendere e riprodurre il problema su un dispositivo interessato.
Il bug è un errore di teardown/ciclo di vita nello scheduler dello scaler. Un processo utente può inviare operazioni asincrone dello scaler, chiudere la connessione IOSurfaceAcceleratorClient che possiede tali operazioni e lasciare voci obsolete in una struttura dello scheduler globale del driver. Un successivo passaggio dello scheduler può quindi elaborare voci che puntano ancora a storage di operazioni già liberato e riutilizzato.
La PoC dimostra il bug del ciclo di vita con due valori di marker distinti:
0xDEAD00010xBEEF0002La connessione vittima invia operazioni asincrone e poi viene chiusa. Le connessioni sostitutive vengono aperte successivamente e impostano il proprio marker a 0xBEEF0002. Quando viene eseguito il successivo ciclo di scheduling dello scaler, il fault osserva il marker sostitutivo (x9 = 0x00000000BEEF0002), non il marker della vittima. Ciò dimostra che lo scheduler ha letto da uno slot di operazione che era stato liberato e poi riallocato a una connessione diversa.
com.apple.driver.AppleM2ScalerCSCDriverIOSurfaceAcceleratorClientget-task-allowAppleM2ScalerCSCDriver mantiene lo stato dello scheduler condiviso tra i client dello scaler. Il disallineamento del ciclo di vita rilevante è:
IOServiceClose.Il percorso di teardown non rimuove le voci dello scheduler in sospeso del client in chiusura dall'heap condiviso dello scheduler. Lo scheduler successivamente legge e scrive campi attraverso quei puntatori obsoleti.
Campi importanti osservati durante l'analisi:
| Offset | Comportamento dello scheduler |
|---|---|
operation + 0xc94 | letto come valore di credito/marker utilizzato dal percorso di risoluzione del credito |
operation + 0xc1c | scritto dal percorso di contabilità crediti dello scheduler |
operation + 0x1fe4 | scritto dal percorso di aggiornamento stato/flag dello scheduler |
Il comportamento dell'allocatore di operazioni rende osservabile il bug: gli slot di operazioni liberati possono essere riutilizzati da operazioni successive di connessioni diverse. Chiudendo una connessione vittima e aprendo immediatamente nuove connessioni spray, la PoC può causare voci dello scheduler obsolete che puntano a memoria ora di proprietà delle connessioni spray.
x9 = 0xBEEF0002 dimostra UAFLa PoC utilizza una distinzione vittima/spray:
0xDEAD0001.0xBEEF0002.Se lo scheduler stesse ancora leggendo oggetti live di proprietà della vittima, il valore osservato sarebbe 0xDEAD0001. Invece, il fault riprodotto osserva 0xBEEF0002, il valore scritto dalle connessioni spray sostitutive. Questa è la prova chiave che lo scheduler sta dereferenziando un puntatore obsoleto in memoria del kernel liberata e riutilizzata.
Questo mostra anche l'impatto cross-connessione: la voce dello scheduler è stata creata da una connessione, ma la memoria che ha successivamente toccato era stata riciclata per un'altra connessione. Nelle esecuzioni riprodotte, l'attività finale dello scheduler potrebbe essere guidata dall'attività normale di SpringBoard/compositor/UI piuttosto che dal processo originale della PoC.
L'avviso pubblico di Apple descrive l'impatto come: “Un'app potrebbe causare una terminazione inaspettata del sistema o leggere la memoria del kernel.”
Dettaglio importante per la riproduzione: dopo aver toccato TEARDOWN UAF, il dispositivo non va necessariamente in panico immediatamente. La PoC prepara prima lo stato obsoleto dello scheduler. Il bug si attiva al successivo ciclo di scheduling dello scaler, che in pratica si verifica quando l'attività di SpringBoard/compositor guida lo scaler. Nella mia riproduzione su dispositivo fisico, ho attivato quel ciclo dello scheduler toccando/interagendo con la Dynamic Island dopo che la PoC ha finito di preparare lo stato obsoleto dello scheduler.
Passaggi:
ScalerTeardownUAF.ipa.AppleM2ScalerCSCDriver.IOSurface di origine/destinazione.0xDEAD0001 sulla connessione vittima.IOServiceClose, liberando gli oggetti delle operazioni di proprietà della vittima mentre rimangono voci dello scheduler obsolete.0xBEEF0002.x9 = 0x00000000BEEF0002.Condizione di prova attesa:
x9 = 0x00000000BEEF0002 significa che lo scheduler ha letto il marker spray dalla memoria che apparteneva originariamente all'operazione vittima liberata.0xBEEF0002 non è il marker della vittima; è il marker della connessione sostitutiva.Il codice sorgente incluso esegue la seguente sequenza:
apri connessione vittima
crea coppia IOSurface sorgente/destinazione
invia richiesta sincrona di base dello scaler
imposta marker vittima = 0xDEAD0001 tramite selettore 10
invia 50 operazioni asincrone dello scaler
chiudi connessione vittima
apri 50 connessioni spray
imposta marker spray = 0xBEEF0002 tramite selettore 10
invia operazioni asincrone ripetute sulle connessioni spray
attendere attivazione scheduler SpringBoard/compositor
Il file sorgente rilevante è ScalerTeardownUAF.m.
xcrun -sdk iphoneos clang -framework Foundation -framework UIKit -framework IOKit \
-framework IOSurface -isysroot $(xcrun --sdk iphoneos --show-sdk-path) \
-arch arm64 -arch arm64e -miphoneos-version-min=16.0 -fobjc-arc \
-o iPhoneProbe.app/iPhoneProbe ScalerTeardownUAF.m
ldid -S entitlements.plist iPhoneProbe.app/iPhoneProbe
mkdir -p /tmp/pkg/Payload
cp -r iPhoneProbe.app /tmp/pkg/Payload/
cd /tmp/pkg && zip -qr ScalerTeardownUAF.ipa Payload
| File | Descrizione |
|---|---|
ScalerTeardownUAF.m | Sorgente Objective-C della PoC che implementa la sequenza di chiusura vittima + riutilizzo spray. |
ScalerTeardownUAF.ipa | Artefatto di riproduzione IPA compilato. |
entitlements.plist | File di autorizzazioni minime contenente get-task-allow. |
AppleM2ScalerCSCDriver.0xDEAD0001, spray 0xBEEF0002.