
CVE-2025-21479 proof-of-concept, penso.
Exploit di root per Quest 3/3S per l'aggiornamento del 7 agosto 2025 e precedenti, basato su CVE-2025-21479.
screenshot di Magisk, Cheese e Termux con una shell di root
Puoi scaricare un APK nella sezione Release.
Vedi la guida di FreeXR per il root del Quest 3/3S.
Unisciti al Discord di FreeXR per maggiori informazioni.
Nessuna versione più recente è supportata. (Le versioni precedenti possono essere supportate con più lavoro.)
Meta ha corretto CVE-2025-21479 in queste versioni e in qualsiasi versione successiva. NON saranno MAI supportate.
Questo repository contiene il sorgente per l'eseguibile da riga di comando cheese.
Il repository cheese-app contiene il sorgente per l'app.
Questo si basa su articoli di altri ricercatori sulla GPU Adreno: utilizza codice da:
Ulteriori informazioni sul firmware delle GPU Adreno, incluso come fare diff del firmware e come funziona il firmware, provengono dalla documentazione afuc di Rob Clark, Connor Abbott e altri contributori di Freedreno/Turnip.
Grazie agli sviluppatori di XRBreak e FreeXR per tutto il loro aiuto e contributi.
====
Proof-of-concept per CVE-2025-21479, che dimostra che colpisce solo i dispositivi Adreno A7xx (Snapdragon 8 Gen 1 / XR2 Gen 2 e successivi).
Questo testa solo se il dispositivo è vulnerabile - ottenere qualcosa di interessante richiederebbe più sforzo.
Su dispositivi Adreno A7xx non patchati, l'esecuzione dovrebbe stampare:
0 0
E se esegui adb bugreport, nel kernel dmesg, vedrai:
<2>[146532.566695][ T933] kgsl kgsl-3d0: GPU PAGE FAULT: addr = 4000031004 pid= 0 name=(null) drawctxt=1111638594 context pid = 0
<2>[146532.566756][ T933] kgsl kgsl-3d0: context=gfx3d_user TTBR0=0x1234567841414141 (write unknown fault)
<2>[146532.566783][ T933] kgsl kgsl-3d0: FAULTING BLOCK: CP
Su dispositivi Adreno A6xx, l'esecuzione stampa:
41414141 42424242
https://notnow.dev/notice/AvIZRBttG7DsDhx9hw
I dispositivi Adreno A7xx patchati (es. dispositivi Samsung dopo l'aggiornamento di sicurezza di maggio 2025) dovrebbero stampare anche questo, ma non l'ho testato.
# adjust path to point to your Android NDK
bash build.sh
adb push cheese /data/local/tmp
adb shell /data/local/tmp/cheese
https://notnow.dev/notice/Av4sfoQjyrxogkZ6Ya
Questo esegue un buffer di comandi sulla GPU Adreno (usando una versione modificata del codice Adrenaline di Project Zero)
Esegue CP_SET_MODE - questo abilita l'esecuzione immediata degli stati di disegno.
Esegue CP_SET_DRAW_STATE - questo imposta IB_LEVEL a 0x4, poi chiama un buffer di istruzioni.
All'interno di CP_SET_DRAW_STATE, esegue CP_SMMU_TABLE_UPDATE.
Ecco la gestione del firmware di CP_SMMU_TABLE_UPDATE:
CP_SMMU_TABLE_UPDATE:
// get IB level
and $02, $12, 0x3
// if not 0 (kernel ring buffer), go to CP_NOP
brne $02, 0x0, #l1873
<actual SMMU modify code >
Quindi con IB_LEVEL=4, mascherando 4 con 3 si ottiene 0, che supera il controllo per il ring buffer del kernel.
Quindi puoi cambiare le tabelle delle pagine e causare un errore della GPU.
Ho fatto il diff di diversi firmware Samsung Galaxy usando il disassemblatore afuc di Freedreno.
Il firmware del Galaxy S24 è stato il più utile, poiché il suo firmware GPU differisce solo per una versione - la correzione di sicurezza:
https://notnow.dev/notice/AuueszvUVUQnWqMQeO
https://notnow.dev/notice/Av0kDfOUPKhqHyjyxE
Galaxy S24 firmware: gen70900_sqe.fw
https://notnow.dev/notice/Av0a7wUouVSa3EKkE4
Il diff del firmware Adreno del Galaxy S24 tra v675 e v676 mostra un tipo di diff:
0163: b80300a4 CP_ME_INIT:
0163: b80300a4 fxn355:
0163: b80300a4 cread $03, [$00 + 0x0a4]
- 0164: 2a440003 and $04, $12, 0x3
+ 0164: 2a440007 and $04, $12, 0x7
0165: 98641813 ushr $03, $03, $04
0166: c860004a brne $03, b0, #l432
0167: 01000000 nop
Ogni accesso a $12 ora fa AND con 0x7 invece di 0x3. Non ci sono altre modifiche.
https://gist.github.com/zhuowei/46a68b9ee53589cdeaa40c11d15d895f
Il registro $12 sembra essere il livello IB: https://gitlab.freedesktop.org/mesa/mesa/-/blob/c0f56fc64cad946d5c4fda509ef3056994c183d9/src/freedreno/afuc/README.rst#id23 https://gitlab.freedesktop.org/mesa/mesa/-/blob/c0f56fc64cad946d5c4fda509ef3056994c183d9/src/freedreno/afuc/README.rst#id29
Che seleziona quale coda di comandi di disegno verrà letta. https://gitlab.freedesktop.org/mesa/mesa/-/blob/c0f56fc64cad946d5c4fda509ef3056994c183d9/src/freedreno/afuc/README.rst#id31
L'hardware Adreno 7xx supporta 5 code (RB (ring buffer del kernel, privilegiato), IB1, IB2, IB3 o SDS): https://cs.android.com/android/platform/superproject/main/+/main:external/mesa3d/src/freedreno/registers/adreno/adreno_control_regs.xml;l=327;drc=c0867f48117dc2c18b1ae689235cb1f60b237600
https://notnow.dev/notice/Av0kDfOUPKhqHyjyxE
Penso che questo diff sia CVE-2025-21479. Sembra che colpisca solo i dispositivi Adreno A7xx (Snapdragon 8 Gen 1 e successivi). Forse il bollettino Qualcomm è sbagliato?
Immagino, su un dispositivo Adreno A7xx:
CP_SET_DRAW_STATECP_SMMU_TABLE_UPDATESecondo il post del blog di Project Zero, l'istruzione CP_INDIRECT_BUFFER chiama un buffer indiretto di istruzioni del processore di controllo,
Quando un'app vuole usare la GPU, il RB (ring buffer del kernel) del kernel conterrà un comando CP_INDIRECT_BUFFER che chiama un buffer indiretto fornito dall'utente - IB1.
Questo buffer utente può chiamare i propri buffer indiretti: IB2.
Su A7xx, c'è anche IB3.
Inoltre, sia su A6xx che su A7xx, c'è SDS, che non viene inserito da buffer indiretto, ma da CP_SET_DRAW_STATE.
https://cs.android.com/android/platform/superproject/+/android15-qpr2-release:external/mesa3d/src/freedreno/decode/cffdec.c;l=3030;drc=0dc791ed57dacf9fe3df694d7f285a8d9f942fa7 https://cs.android.com/android/platform/superproject/+/android15-qpr2-release:external/mesa3d/src/freedreno/decode/cffdec.c;l=2283;drc=0dc791ed57dacf9fe3df694d7f285a8d9f942fa7
A6xx ha RB, IB1, IB2 e SDS.
CP_SET_DRAW_STATE imposta il livello IB a 0x3: in a650_sqe.fw.v114 del firmware Galaxy Fold 3:
mov $03, 0x3
or $12, $12, 0x20
call #fxn1132 // there's a branch delay slot, so this isn't executed yet...
cwrite $03, [$00 + @IB_LEVEL]
Ma A7xx ora ha RB, IB1, IB2, IB3 o SDS.
CP_SET_DRAW_STATE ora imposta il livello IB a 0x4:
mov $03, 0x4
cwrite $03, [$00 + @IB_LEVEL]
0x4 & 0x3 = 0x0.
Quindi il codice che controlla il livello IB corrente penserà che SDS (set draw state) sia RB (ring buffer del kernel), e comandi come CP_SMMU_TABLE_UPDATE permetteranno l'esecuzione.