Adreno A7xx SDS->RB privilege bypass (GPU SMMU takeover to Kernel R/W)
Tip
AWSハッキングを学び、実践する:
HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。
このページでは、実際に確認された Adreno A7xx の microcode ロジックバグ (CVE-2025-21479) を再現可能なエクスプロイト手法に抽象化します: Set Draw State (SDS) における IB-level マスキングを悪用して非特権アプリから特権 GPU パケットを実行し、GPU SMMU の乗っ取りへピボットして、dirty-pagetable trick による高速で安定したカーネルの R/W を達成します。
- 影響: $12 レジスタのマスクを 0x3 から 0x7 に変更する microcode 修正以前の Qualcomm Adreno A7xx GPU firmware が影響を受けます。
- プリミティブ: SDS(ユーザ制御)から特権 CP パケット(例: CP_SMMU_TABLE_UPDATE)を実行。
- 結果: 任意の物理/仮想カーネルメモリの R/W、SELinux 無効化、root 権限取得。
- 前提: KGSL GPU コンテキストを作成し、SDS に入るコマンドバッファを送信できること(通常のアプリ機能)。
背景: IB levels, SDS and the $12 mask
- カーネルは ringbuffer (RB=IB0) を維持。ユーザー空間は CP_INDIRECT_BUFFER 経由で IB1 を送信し、IB2/IB3 にチェーンする。
- SDS は CP_SET_DRAW_STATE を通じて入る特殊なコマンドストリーム:
- A6xx: SDS は IB3 とみなされる
- A7xx: SDS は IB4 に移動した
- Microcode は現在の IB レベルを $12 レジスタで追跡し、実効レベルが IB0(カーネル RB)に対応する場合のみ特権パケットを受け付けるようゲートしている。
- バグ: A7xx microcode は $12 を 0x3 (2 ビット) でマスクしたままで、0x7 (3 ビット) ではなかった。IB4 & 0x3 == 0 となるため、SDS は誤って IB0 と識別され、ユーザー制御の SDS からの特権パケットが許可されてしまった。
なぜ重要か:
A6XX | A7XX
RB & 3 == 0 | RB & 3 == 0
IB1 & 3 == 1 | IB1 & 3 == 1
IB2 & 3 == 2 | IB2 & 3 == 2
IB3 (SDS) & 3 == 3 | IB3 & 3 == 3
| IB4 (SDS) & 3 == 0 <-- misread as IB0 if mask is 0x3
Microcode diffの例 (パッチによりマスクが0x7に切り替えられた):
@@ CP_SMMU_TABLE_UPDATE
- and $02, $12, 0x3
+ and $02, $12, 0x7
@@ CP_FIXED_STRIDE_DRAW_TABLE
- and $02, $12, 0x3
+ and $02, $12, 0x7
Exploitation overview
Goal: From SDS (misread as IB0) issue privileged CP packets to re-point the GPU SMMU to attacker-crafted page tables, then use GPU copy/write packets for arbitrary physical R/W. Finally, pivot to a fast CPU-side R/W via dirty pagetable.
High-level chain
- Craft a fake GPU pagetable in shared memory
- Enter SDS and execute:
- CP_SMMU_TABLE_UPDATE -> switch to fake pagetable
- CP_MEM_WRITE / CP_MEM_TO_MEM -> implement write/read primitives
- CP_SET_DRAW_STATE with run-now flags (dispatch immediately)
GPU R/W primitives via fake pagetable
- Write: CP_MEM_WRITE to an attacker-chosen GPU VA whose PTEs you map to a chosen PA -> arbitrary physical write
- Read: CP_MEM_TO_MEM copies 4/8 bytes from target PA to a userspace-shared buffer (batch for larger reads)
Notes
- Each Android process gets a KGSL context (IOCTL_KGSL_GPU_CONTEXT_CREATE). Switching contexts normally updates SMMU tables in the RB; the bug lets you do it in SDS.
- Excessive GPU traffic can cause UI blackouts and reboots; reads are small (4/8B) and sync is slow by default.
Building the SDS command sequence
- Spray a fake GPU pagetable into shared memory so at least one instance lands at a known physical address (e.g., via allocator grooming and repetition).
- Construct an SDS buffer containing, in order:
- CP_SMMU_TABLE_UPDATE to the physical address of the fake pagetable
- One or more CP_MEM_WRITE and/or CP_MEM_TO_MEM packets to implement R/W using your new translations
- CP_SET_DRAW_STATE with flags to run-now
The exact packet encodings vary by firmware; use freedreno’s afuc/packet docs to assemble the words, and ensure the SDS submission path is taken by the driver.
Finding Samsung kernel physbase under physical KASLR
Samsung randomizes the kernel physical base within a known region on Snapdragon devices. Brute-force the expected range and look for the first 16 bytes of _stext.
Representative loop
while (!ctx->kernel.pbase) {
offset += 0x8000;
uint64_t d1 = kernel_physread_u64(ctx, base + offset);
if (d1 != 0xd10203ffd503233f) continue; // first 8 bytes of _stext
uint64_t d2 = kernel_physread_u64(ctx, base + offset + 8);
if (d2 == 0x910083fda9027bfd) { // second 8 bytes of _stext
ctx->kernel.pbase = base + offset - 0x10000;
break;
}
}
physbase が判明したら、線形マップを使ってカーネル仮想アドレスを計算する:
_stext = 0xffffffc008000000 + (Kernel Code & ~0xa8000000)
高速で信頼性のある CPU 側カーネル R/W(dirty pagetable)への安定化
GPU R/W は遅く粒度が小さい。自プロセスの PTEs を破損させて高速で安定した primitive(“dirty pagetable”)にピボットする:
Steps
- 遅い GPU R/W primitives を使用して現在の task_struct -> mm_struct -> mm_struct->pgd を特定する
- mmap で隣接するユーザ空間ページ A と B を割り当てる(例: 0x1000)
- PGD->PMD->PTE を辿って A/B の PTE の物理アドレスを特定する(helpers: get_pgd_offset, get_pmd_offset, get_pte_offset)
- B の PTE を上書きして A/B を管理する最下位の pagetable を RW 属性で指すようにする(phys_to_readwrite_pte)
- B の VA を介して書き込み、A の PTE を変更して目的の PFNs をマップさせる;A の VA 経由でカーネルメモリを読み書きし、TLB をフラッシュして sentinel が反転するまで繰り返す
例: dirty-pagetable pivot snippet
```c uint64_t *map = mmap((void*)0x1000, PAGE_SIZE*2, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); uint64_t *page_map = (void*)((uint64_t)map + PAGE_SIZE); page_map[0] = 0x4242424242424242;uint64_t tsk = get_curr_task_struct(ctx); uint64_t mm = kernel_vread_u64(ctx, tsk + OFFSETOF_TASK_STRUCT_MM); uint64_t mm_pgd = kernel_vread_u64(ctx, mm + OFFSETOF_MM_PGD);
uint64_t pgd_off = get_pgd_offset((uint64_t)map); uint64_t phys_pmd = kernel_vread_u64(ctx, mm_pgd + pgd_off) & ~((1<<12)-1); uint64_t pmd_off = get_pmd_offset((uint64_t)map); uint64_t phys_pte = kernel_pread_u64(ctx, phys_pmd + pmd_off) & ~((1<<12)-1); uint64_t pte_off = get_pte_offset((uint64_t)map); uint64_t pte_addr = phys_pte + pte_off; uint64_t new_pte = phys_to_readwrite_pte(pte_addr); kernel_write_u64(ctx, pte_addr + 8, new_pte, false); while (page_map[0] == 0x4242424242424242) flush_tlb();
</details>
## 検出
- テレメトリ: CP_SMMU_TABLE_UPDATE (or similar privileged opcodes) appears outside RB/IB0, especially in SDS; monitor anomalous bursts of 4/8-byte CP_MEM_TO_MEM and excessive TLB flush patterns
## 影響
GPU アクセスを持つローカルアプリは特権 GPU パケットを実行し、GPU SMMU をハイジャックして任意のカーネル物理/仮想 R/W を実現し、SELinux を無効化して影響を受ける Snapdragon A7xx デバイス(例: Samsung S23)で root を取得できます。重大度: 高(カーネルの乗っ取り)。
### 参照
<a class="content_ref" href="pixel-bigwave-bigo-job-timeout-uaf-kernel-write.md"><span class="content_ref_label">Pixel Bigwave Bigo Job Timeout Uaf Kernel Write</span></a>
## 参考
- [CVE-2025-21479: Adreno A7xx SDS->RB privilege bypass to kernel R/W (Samsung S23)](https://xploitbengineer.github.io/CVE-2025-21479)
- [Mesa freedreno afuc disassembler README (microcode + packets)](https://gitlab.freedesktop.org/mesa/mesa/-/blob/c0f56fc64cad946d5c4fda509ef3056994c183d9/src/freedreno/afuc/README.rst)
- [Google Project Zero: Attacking Qualcomm Adreno GPU (SMMU takeover via CP packets)](https://googleprojectzero.blogspot.com/2020/09/attacking-qualcomm-adreno-gpu.html)
- [Dirty pagetable (archive)](https://web.archive.org/web/20240425043203/https://yanglingxi1993.github.io/dirty_pagetable/dirty_pagetable.html)
> [!TIP]
> AWSハッキングを学び、実践する:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> GCPハッキングを学び、実践する:<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
> Azureハッキングを学び、実践する:<img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training Azure Red Team Expert (AzRTE)**](https://training.hacktricks.xyz/courses/azrte)<img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
>
> <details>
>
> <summary>HackTricksをサポートする</summary>
>
> - [**サブスクリプションプラン**](https://github.com/sponsors/carlospolop)を確認してください!
> - **💬 [**Discordグループ**](https://discord.gg/hRep4RUj7f)または[**テレグラムグループ**](https://t.me/peass)に参加するか、**Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**をフォローしてください。**
> - **[**HackTricks**](https://github.com/carlospolop/hacktricks)および[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud)のGitHubリポジトリにPRを提出してハッキングトリックを共有してください。**
>
> </details>


