Adreno A7xx SDS->RB विशेषाधिकार बायपास (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 का समर्थन करें

यह पृष्ठ एक वास्तविक दुनिया के Adreno A7xx microcode लॉजिक बग (CVE-2025-21479) को पुनरुत्पादनीय explotitation तकनीकों में सारांशित करता है: Set Draw State (SDS) में IB-स्तर मास्किंग का दुरुपयोग करके एक अनप्रिविलेज्ड ऐप से privileged GPU packets execute करना, GPU SMMU takeover की ओर pivot करना और फिर dirty-pagetable trick के माध्यम से एक तेज़, स्थिर kernel R/W प्राप्त करना।

  • Affected: Qualcomm Adreno A7xx GPU firmware prior to a microcode fix that changed masking of register $12 from 0x3 to 0x7.
  • Primitive: Execute privileged CP packets (e.g., CP_SMMU_TABLE_UPDATE) from SDS, which is user-controlled.
  • Outcome: Arbitrary physical/virtual kernel memory R/W, SELinux disable, root.
  • Prereq: Ability to create a KGSL GPU context and submit command buffers that enter SDS (normal app capability).

Background: IB levels, SDS and the $12 mask

  • Kernel एक ringbuffer बनाए रखता है (RB=IB0). Userspace CP_INDIRECT_BUFFER के माध्यम से IB1 सबमिट करता है, जो IB2/IB3 तक chaining करता है।
  • SDS एक विशेष command stream है जिसे CP_SET_DRAW_STATE के माध्यम से enter किया जाता है:
  • A6xx: SDS को IB3 माना जाता है
  • A7xx: SDS को IB4 में स्थानांतरित किया गया
  • Microcode current IB level को register $12 में ट्रैक करता है और privileged packets को gate करता है ताकि वे केवल तभी स्वीकार किए जाएं जब effective level IB0 (kernel RB) के अनुरूप हो।
  • Bug: A7xx microcode ने $12 को 0x3 (2 bits) से mask करते रखा बजाय 0x7 (3 bits) के। चूंकि IB4 & 0x3 == 0, SDS को गलत तरीके से IB0 के रूप में पहचाना जाता था, जिससे user-controlled SDS से privileged packets की अनुमति मिल गई।

Why it matters:

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 उदाहरण (patch switched the mask to 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

  • एक नकली GPU pagetable शेयर की हुई मेमोरी में बनाएं
  • SDS में प्रवेश करें और execute करें:
  • CP_SMMU_TABLE_UPDATE -> नकली pagetable पर switch करें
  • CP_MEM_WRITE / CP_MEM_TO_MEM -> write/read primitives लागू करें
  • CP_SET_DRAW_STATE with run-now flags (तुरंत dispatch)

GPU R/W primitives via fake pagetable

  • Write: CP_MEM_WRITE को एक attacker-chosen GPU VA पर भेजें जिनके PTEs आप किसी चुने हुए PA पर map करते हैं -> arbitrary physical write
  • Read: CP_MEM_TO_MEM target PA से userspace-shared buffer में 4/8 bytes copy करता है (बड़े reads के लिए batch करें)

Notes

  • प्रत्येक Android प्रक्रिया को एक KGSL context (IOCTL_KGSL_GPU_CONTEXT_CREATE) मिलता है। सामान्यतः contexts बदलने से SMMU tables RB में update होते हैं; यह bug आपको इसे SDS में करने देता है।
  • अत्यधिक GPU ट्रैफ़िक UI blackouts और reboots का कारण बन सकता है; reads छोटे होते हैं (4/8B) और sync default पर slow होता है।

Building the SDS command sequence

  • एक नकली GPU pagetable को शेयर की हुई मेमोरी में spray करें ताकि कम से कम एक उदाहरण एक ज्ञात physical address पर आए (उदा., allocator grooming और repetition के ज़रिए)।
  • एक SDS buffer बनाएं जिसमें, क्रमशः, यह शामिल हो:
  1. CP_SMMU_TABLE_UPDATE नकली pagetable के physical address पर
  2. एक या अधिक CP_MEM_WRITE और/या CP_MEM_TO_MEM packets ताकि आपकी नई translations का उपयोग कर R/W किया जा सके
  3. CP_SET_DRAW_STATE उन flags के साथ जो run-now करें

Exact packet encodings firmware के अनुसार बदलते हैं; freedreno’s afuc/packet docs का उपयोग करके words assemble करें, और सुनिश्चित करें कि driver द्वारा SDS submission path लिया जा रहा है।

Finding Samsung kernel physbase under physical KASLR

Samsung Snapdragon डिवाइसेज़ पर kernel physical base को एक ज्ञात region के भीतर randomize करता है। अनुमानित range को brute-force करें और _stext के पहले 16 bytes देखें।

प्रतिनिधि लूप

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 ज्ञात हो, linear map के साथ kernel virtual की गणना करें:

_stext = 0xffffffc008000000 + (Kernel Code & ~0xa8000000)

तेज़, विश्वसनीय CPU-साइड kernel R/W (dirty pagetable) पर स्थिरीकरण

GPU R/W धीमा है और इसकी ग्रैन्युलैरिटी छोटी है। अपने प्रोसेस के PTEs को करप्ट करके (“dirty pagetable”) एक तेज़/स्थिर primitive पर Pivot करें:

Steps

  • धीमे GPU R/W primitives का उपयोग करके current task_struct -> mm_struct -> mm_struct->pgd को ढूँढें
  • दो सन्निकट userspace पेज A और B को mmap करें (उदा., at 0x1000)
  • A/B के PTE के physical addresses को रिज़ॉल्व करने के लिए PGD->PMD->PTE ट्रैवर्स करें (helpers: get_pgd_offset, get_pmd_offset, get_pte_offset)
  • B के PTE को ओवरराइट करके उसे A/B को मैनेज करने वाले last-level pagetable की ओर पॉइंट कराएँ और RW attributes सेट करें (phys_to_readwrite_pte)
  • B के VA के माध्यम से लिखकर A के PTE को बदलें ताकि target PFNs मैप हों; A के VA से kernel memory को पढ़ें/लिखें, और 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>

## पता लगाना

- Telemetry: चेतावनी जब CP_SMMU_TABLE_UPDATE (या समान privileged opcodes) RB/IB0 के बाहर दिखाई दे, खासकर SDS में; 4/8-बाइट CP_MEM_TO_MEM के अनियम्य बर्स्ट और अत्यधिक TLB फ्लश पैटर्न की निगरानी रखें

## प्रभाव

एक स्थानीय ऐप जिसके पास GPU एक्सेस है privileged GPU packets चला सकता है, GPU SMMU को हाईजैक कर सकता है, मनमानी kernel physical/virtual 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) गिटहब रिपोजिटरी में PRs सबमिट करें।
>
> </details>