
CVE-2025-21479 の概念実証、だと思う
Root exploit for the Quest 3/3S for the August 7, 2025 update and earlier, based on CVE-2025-21479.
Magisk、Cheese、Termux でルートシェルを表示したスクリーンショット
ルート化は危険です。Quest 3/3S を文鎮化(ブリック)した場合、修復する方法はありません。
一時ルート化中は、すべてのセキュリティが無効になります。
信頼できないアプリの実行やウェブサイトの閲覧をしないでください。
boot または system パーティションに書き込まないでください。文鎮化(ブリック)します。
Magisk の「Install」機能を使用しないでください。
ルート化後は、deviceKey、Meta Access Token、Oculus Access Token をバックアップすることをお勧めします。
APK は Release セクションからダウンロードできます。
FreeXR の Quest 3/3S ルート化ガイド を参照してください。
詳細は FreeXR の Discord に参加してください。
新しいバージョンはサポートされていません。(古いバージョンは追加の作業によりサポート可能です。)
Meta はこれらのバージョンおよびそれ以降の新しいバージョンで CVE-2025-21479 を修正しました。これらのバージョンは決してサポートされません。
このリポジトリには、コマンドライン実行ファイル cheese のソースコードが含まれています。
アプリのソースコードは cheese-app リポジトリに含まれています。
これは他の研究者による Adreno GPU の解析記事に基づいています。以下のコードを使用しています:
Adreno GPU ファームウェアに関する追加情報(ファームウェアの diff の取り方や、ファームウェアの仕組みを含む)は、Rob Clark、Connor Abbott、および他の Freedreno/Turnip コントリビューターによる Freedreno の afuc ドキュメント から得ています。
XRBreak と FreeXR の開発者の皆様のご支援とご貢献に感謝します。
====
CVE-2025-21479 の概念実証(Proof-of-Concept)。この脆弱性が Adreno A7xx(Snapdragon 8 Gen 1 / XR2 Gen 2 以降)デバイスのみに影響することを示しています。
これはデバイスに脆弱性があるかどうかをテストするだけです。実際に何か興味深い動作をさせるには、さらなる作業が必要です。
パッチ未適用の Adreno A7xx デバイスでは、これを実行すると次のように表示されます:
0 0
また、adb bugreport を実行すると、カーネルの dmesg に次のように表示されます:
<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
Adreno A6xx デバイスでは、これを実行すると次のように表示されます:
41414141 42424242
https://notnow.dev/notice/AvIZRBttG7DsDhx9hw
パッチ適用済みの Adreno A7xx(例: 2025年5月のセキュリティ更新プログラム 適用後の Samsung デバイス)でもこれと同じ出力になるはずですが、私はテストしていません。
# 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
これは(Project Zero の Adrenaline コード の修正版を使用して)Adreno GPU 上でコマンドバッファを実行します。
CP_SET_MODE を実行します。これにより、draw state が即座に実行されるようになります。
CP_SET_DRAW_STATE を実行します。これにより IB_LEVEL が 0x4 に設定され、その後命令バッファを呼び出します。
CP_SET_DRAW_STATE 内で CP_SMMU_TABLE_UPDATE を実行します。
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 >
つまり、IB_LEVEL=4 の場合、4 を 3 でマスクすると 0 になり、カーネルリングバッファのチェックを通過します。
これによりページテーブルを変更でき、GPU にエラーを発生させることができます。
Freedreno の afuc 逆アセンブラを使用して、いくつかの Samsung Galaxy ファームウェアを diff しました。
Galaxy S24 のファームウェアが最も役立ちました。GPU ファームウェアの差分が、セキュリティ修正の1バージョンだけだからです:
https://notnow.dev/notice/AuueszvUVUQnWqMQeO
https://notnow.dev/notice/Av0kDfOUPKhqHyjyxE
Galaxy S24 ファームウェア: gen70900_sqe.fw
https://notnow.dev/notice/Av0a7wUouVSa3EKkE4
Galaxy S24 の Adreno ファームウェアを v675 と v676 で diff すると、1種類の差分が表示されます:
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
$12 へのすべてのアクセスが、0x3 の代わりに 0x7 で AND を取るようになりました。他の変更はありません。
https://gist.github.com/zhuowei/46a68b9ee53589cdeaa40c11d15d895f
レジスタ $12 は 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
これにより、どの drawing コマンドのキューが読み取られるかが選択されます。 https://gitlab.freedesktop.org/mesa/mesa/-/blob/c0f56fc64cad946d5c4fda509ef3056994c183d9/src/freedreno/afuc/README.rst#id31
Adreno 7xx ハードウェアは 5 つのキュー(RB(カーネルリングバッファ、特権)、IB1、IB2、IB3、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
この差分が CVE-2025-21479 だと思います。 これは Adreno A7xx デバイス(Snapdragon 8 Gen 1 以降)のみに影響するようです。 もしかすると Qualcomm のセキュリティ情報 は間違っているのでしょうか?
推測ですが、Adreno A7xx デバイスでは:
CP_SET_DRAW_STATE を使って IB レベル 4(SDS)でコマンドを実行できた場合、CP_SMMU_TABLE_UPDATE のように IB レベル = RB(カーネル提供のリングバッファ)をチェックするコマンドを見つけた場合、Project Zero のブログ記事 によると、CP_INDIRECT_BUFFER 命令は制御プロセッサ命令の間接バッファを呼び出します。
アプリが GPU を使用したい場合、カーネルの RB(カーネルリングバッファ)には、ユーザーが提供した間接バッファ(IB1)を呼び出す CP_INDIRECT_BUFFER コマンドが含まれます。このユーザーバッファは、自身の間接バッファ(IB2)を呼び出すことができます。A7xx には IB3 もあります。
さらに、A6xx と A7xx の両方に SDS があります。SDS は間接バッファではなく、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 には RB、IB1、IB2、SDS があります。
CP_SET_DRAW_STATE は IB レベルを 0x3 に設定します。Galaxy Fold 3 ファームウェアの a650_sqe.fw.v114 では:
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]
一方、A7xx には現在 RB、IB1、IB2、IB3、SDS があります。
CP_SET_DRAW_STATE は現在、IB レベルを 0x4 に設定します:
mov $03, 0x4
cwrite $03, [$00 + @IB_LEVEL]
0x4 & 0x3 = 0x0。
そのため、現在の IB レベルをチェックするコードは、SDS(set draw state)を RB(カーネルリングバッファ)と誤認し、CP_SMMU_TABLE_UPDATE などのコマンドの実行が許可されます。