
CVE-2025-21479 preuve de concept, je pense
Exploit racine pour le Quest 3/3S pour la mise à jour du 7 août 2025 et antérieure, basé sur CVE-2025-21479.
capture d'écran de Magisk, Cheese et Termux avec un shell root
Vous pouvez télécharger un APK dans la section Release.
Voir le guide de FreeXR pour rooter le Quest 3/3S.
Rejoignez le Discord de FreeXR pour plus d’informations.
Aucune version plus récente n’est supportée. (Les versions plus anciennes peuvent être supportées avec plus de travail.)
Meta a corrigé CVE-2025-21479 dans ces versions et toutes les versions plus récentes. Elles ne seront JAMAIS supportées.
Ce dépôt contient le code source de l’exécutable en ligne de commande cheese.
Le dépôt cheese-app contient le code source de l’application.
Ceci est basé sur les travaux d’autres chercheurs sur le GPU Adreno : ce code utilise du code provenant de :
Des informations supplémentaires sur le firmware des GPU Adreno, y compris comment différencier le firmware et comment il fonctionne, proviennent de la documentation afuc de Freedreno, par Rob Clark, Connor Abbott et d’autres contributeurs de Freedreno/Turnip.
Merci aux développeurs de XRBreak et FreeXR pour toute leur aide et leurs contributions.
====
Preuve de concept pour CVE-2025-21479, démontrant qu’elle n’affecte que les appareils Adreno A7xx (Snapdragon 8 Gen 1 / XR2 Gen 2 et plus récents).
Ceci teste uniquement si l’appareil est vulnérable – faire en sorte que cela fasse réellement quelque chose d’intéressant nécessiterait davantage d’efforts.
Sur les appareils Adreno A7xx non corrigés, l’exécution de ceci devrait afficher :
0 0
Et si vous exécutez adb bugreport, dans le dmesg du noyau, vous verrez :
<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
Sur les appareils Adreno A6xx, l’exécution de ceci affiche :
41414141 42424242
https://notnow.dev/notice/AvIZRBttG7DsDhx9hw
Les Adreno A7xx corrigés (par exemple, les appareils Samsung après la mise à jour de sécurité de mai 2025) devraient également afficher ceci, mais je ne l’ai pas testé.
# ajustez le chemin vers votre NDK Android
bash build.sh
adb push cheese /data/local/tmp
adb shell /data/local/tmp/cheese
https://notnow.dev/notice/Av4sfoQjyrxogkZ6Ya
Ceci exécute un tampon de commandes sur le GPU Adreno (en utilisant une version modifiée du code Adrenaline de Project Zero)
Exécutez CP_SET_MODE – cela permet aux états de dessin de s’exécuter immédiatement.
Exécutez CP_SET_DRAW_STATE – cela définit IB_LEVEL à 0x4, puis appelle un tampon d’instructions.
À l’intérieur du CP_SET_DRAW_STATE, exécutez CP_SMMU_TABLE_UPDATE.
Voici le traitement du firmware pour 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 >
Donc avec IB_LEVEL=4, le masquage de 4 avec 3 donne 0, ce qui passe la vérification pour le tampon en anneau du noyau.
Ainsi, vous pouvez modifier les tables de pages et faire en sorte que le GPU génère une erreur.
J’ai différencié plusieurs firmwares Samsung Galaxy en utilisant le désassembleur afuc de Freedreno.
Le firmware du Galaxy S24 a été le plus utile, car son firmware GPU ne diffère que d’une version – le correctif de sécurité :
https://notnow.dev/notice/AuueszvUVUQnWqMQeO
https://notnow.dev/notice/Av0kDfOUPKhqHyjyxE
Firmware du Galaxy S24 : gen70900_sqe.fw
https://notnow.dev/notice/Av0a7wUouVSa3EKkE4
La comparaison du firmware Adreno du Galaxy S24 entre v675 et v676 montre un type de différence :
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
Désormais, chaque accès à $12 effectue un ET avec 0x7 au lieu de 0x3. Il n’y a aucun autre changement.
https://gist.github.com/zhuowei/46a68b9ee53589cdeaa40c11d15d895f
Le registre $12 semble être le niveau 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
Qui sélectionne la file d’attente des commandes de dessin à lire. https://gitlab.freedesktop.org/mesa/mesa/-/blob/c0f56fc64cad946d5c4fda509ef3056994c183d9/src/freedreno/afuc/README.rst#id31
Le matériel Adreno 7xx prend en charge 5 files d’attente (RB (tampon en anneau du noyau, privilégié), IB1, IB2, IB3, ou 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
Je pense que cette différence est CVE-2025-21479. Il semble que cela n’affecte que les appareils Adreno A7xx (Snapdragon 8 Gen 1 et supérieur). Peut-être que le bulletin Qualcomm est erroné ?
Je suppose, sur un appareil Adreno A7xx :
CP_SET_DRAW_STATECP_SMMU_TABLE_UPDATESelon le blog de Project Zero, l’instruction CP_INDIRECT_BUFFER appelle un tampon indirect d’instructions du processeur de contrôle.
Lorsqu’une application souhaite utiliser le GPU, le RB (tampon en anneau du noyau) contient une commande CP_INDIRECT_BUFFER qui appelle un tampon indirect fourni par l’utilisateur – IB1.
Ce tampon utilisateur peut appeler ses propres tampons indirects : IB2.
Sur A7xx, il y a aussi IB3.
De plus, sur A6xx et A7xx, il y a SDS, qui n’est pas atteint par un tampon indirect, mais par 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 a RB, IB1, IB2 et SDS.
CP_SET_DRAW_STATE définit le niveau IB à 0x3 : dans a650_sqe.fw.v114 du firmware du 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]
Mais A7xx a maintenant RB, IB1, IB2, IB3 ou SDS.
CP_SET_DRAW_STATE définit maintenant le niveau IB à 0x4 :
mov $03, 0x4
cwrite $03, [$00 + @IB_LEVEL]
0x4 & 0x3 = 0x0.
Ainsi, le code vérifiant le niveau IB actuel pensera que SDS (set draw state) est RB (tampon en anneau du noyau), et des commandes comme CP_SMMU_TABLE_UPDATE seront autorisées à s’exécuter.