
CVE-2025-21479 prueba de concepto, creo
Exploit de root para Quest 3/3S hasta la actualización del 7 de agosto de 2025 y anteriores, basado en CVE-2025-21479.
captura de pantalla de Magisk, Cheese y Termux con una shell de root
Rootear es peligroso. Si brickeeas un Quest 3/3S, no hay forma de repararlo.
Esto desactiva toda la seguridad cuando se hace root temporal.
NO ejecutes aplicaciones ni navegues por sitios web en los que no confíes.
NO escribas en la partición de boot ni en la de sistema. BRICKEEARÁS el dispositivo.
Es posible que quieras hacer una copia de seguridad de tu deviceKey, Meta Access Token y Oculus Access Token después del root.
Puedes descargar un APK en la sección Release.
Consulta la guía de FreeXR para rootear el Quest 3/3S.
Únete al Discord de FreeXR para obtener más información.
No se admiten versiones más recientes. (Las versiones anteriores se pueden admitir con más trabajo.)
Meta parcheó CVE-2025-21479 en estas versiones y en cualquier versión posterior. NUNCA serán compatibles.
Este repositorio contiene el código fuente del ejecutable cheese de línea de comandos.
El repositorio cheese-app contiene el código fuente de la aplicación.
Esto se basa en los análisis de otros investigadores sobre la GPU Adreno: utiliza código de:
Información adicional sobre el firmware de las GPU Adreno, incluido cómo hacer diff del firmware y cómo funciona el firmware, proviene de la documentación de afuc de Freedreno, escrita por Rob Clark, Connor Abbott y otros colaboradores de Freedreno/Turnip.
Gracias a los desarrolladores de XRBreak y FreeXR por toda su ayuda y contribuciones.
====
Prueba de concepto para CVE-2025-21479, que demuestra que solo afecta a los dispositivos Adreno A7xx (Snapdragon 8 Gen 1 / XR2 Gen 2 y posteriores).
Esto solo comprueba si el dispositivo es vulnerable: lograr que haga algo realmente interesante requeriría más esfuerzo.
En dispositivos Adreno A7xx sin parchear, ejecutar esto debería imprimir:
0 0
Y si ejecutas adb bugreport, en el dmesg del kernel verás:
<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
En dispositivos Adreno A6xx, ejecutar esto imprime:
41414141 42424242
https://notnow.dev/notice/AvIZRBttG7DsDhx9hw
Los Adreno A7xx parcheados (p. ej., dispositivos Samsung posteriores a la actualización de seguridad de mayo de 2025) también deberían imprimir esto, pero no lo he probado.
# 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
Esto ejecuta un búfer de comandos en la GPU Adreno (usando una versión modificada del código de Adrenaline de Project Zero)
Ejecuta CP_SET_MODE: esto permite que los estados de dibujo se ejecuten de inmediato.
Ejecuta CP_SET_DRAW_STATE: esto establece IB_LEVEL en 0x4 y luego llama a un búfer de instrucciones.
Dentro del CP_SET_DRAW_STATE, ejecuta CP_SMMU_TABLE_UPDATE.
Así es como el firmware maneja 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 >
Entonces, con IB_LEVEL=4, enmascarar 4 con 3 da 0, lo que supera la comprobación del búfer de anillo del kernel.
Por lo tanto, puedes cambiar las tablas de páginas y provocar que la GPU falle.
Hice el diff de varios firmware de Samsung Galaxy usando el desensamblador afuc de Freedreno.
El firmware del Galaxy S24 fue el más útil, ya que su firmware de GPU solo difiere en una versión: la corrección de seguridad:
https://notnow.dev/notice/AuueszvUVUQnWqMQeO
https://notnow.dev/notice/Av0kDfOUPKhqHyjyxE
Firmware del Galaxy S24: gen70900_sqe.fw
https://notnow.dev/notice/Av0a7wUouVSa3EKkE4
Hacer el diff del firmware Adreno del Galaxy S24 entre v675 y v676 muestra un tipo de 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
Cada acceso a $12 ahora hace AND con 0x7 en lugar de 0x3. No hay otros cambios.
https://gist.github.com/zhuowei/46a68b9ee53589cdeaa40c11d15d895f
El registro $12 parece ser el nivel de 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
Que selecciona qué cola de comandos de dibujo se leerá. https://gitlab.freedesktop.org/mesa/mesa/-/blob/c0f56fc64cad946d5c4fda509ef3056994c183d9/src/freedreno/afuc/README.rst#id31
El hardware Adreno 7xx admite 5 colas (RB (búfer de anillo del kernel, privilegiado), 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
Creo que este diff es CVE-2025-21479. Parece que solo afecta a los dispositivos Adreno A7xx (Snapdragon 8 Gen 1 y superiores). ¿Quizás el boletín de Qualcomm esté equivocado?
Supongo que, en un dispositivo Adreno A7xx:
CP_SET_DRAW_STATECP_SMMU_TABLE_UPDATESegún la publicación del blog de Project Zero, la instrucción CP_INDIRECT_BUFFER llama a un búfer indirecto de instrucciones del procesador de control,
Cuando una aplicación quiere usar la GPU, el RB del kernel (búfer de anillo del kernel) contendrá un comando CP_INDIRECT_BUFFER que llama a un búfer indirecto proporcionado por el usuario: IB1.
Este búfer de usuario puede llamar a sus propios búferes indirectos: IB2.
En A7xx, también está IB3.
Además, tanto en A6xx como en A7xx, está SDS, al que no se accede mediante un búfer indirecto, sino mediante 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 tiene RB, IB1, IB2 y SDS.
CP_SET_DRAW_STATE establece el nivel de IB en 0x3: en a650_sqe.fw.v114 del firmware del 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]
Pero A7xx ahora tiene RB, IB1, IB2, IB3 o SDS.
CP_SET_DRAW_STATE ahora establece el nivel de IB en 0x4:
mov $03, 0x4
cwrite $03, [$00 + @IB_LEVEL]
0x4 & 0x3 = 0x0.
Por lo tanto, el código que comprueba el nivel de IB actual pensará que SDS (set draw state) es RB (búfer de anillo del kernel), y comandos como CP_SMMU_TABLE_UPDATE permitirán la ejecución.