Texture mipmap BO bounds check is commented out (GPU OOB mip walk past mipmap BO)
Summary
r600_check_texture_resource computes mipmap_size via r600_texture_size and then does nothing: the entire bounds-check body is commented out. Any LAST_LEVEL/BASE_LEVEL/mip-offset combination is accepted regardless of mipmap BO size (the l0_size check covers only level-0). texmip_sim: 512x512 R8, 10 levels vs a 256-byte mipmap BO -> sampler walks 87,125 bytes past the BO. Cross-process GPU disclosure. Restore-check-with-u64 fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4032 Β· 12 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 553 B | β raw | |
| VERDICT.md | β | 2.7 KB | β raw | |
| build.log | β | 1.1 KB | view raw | |
| build.sh | β | 65 B | view raw | |
| env.txt | β | 586 B | view raw | |
| fix.diff | β | 667 B | view raw | |
| r600_cs_poc.c | β | 11.6 KB | view raw | |
| run.2.log | β | 881 B | view raw | |
| run.log | β | 812 B | view raw | |
| run.sh | β | 89 B | view raw | |
| texmip_sim.c | β | 1.9 KB | view raw | |
| verdict.json | β | 2.5 KB | view raw |
DF-4032 evidence pack
r600_check_texture_resource's mipmap BO bounds check is commented out (r600_cs.c:1603-1606): any LAST_LEVEL/BASE_LEVEL/word3 mip offset is accepted regardless of mipmap BO size. texmip_sim (run.log) s
Build
./build.sh (cc -O2 -Wall; verified on the DragonFly audit guest β build.log)
Run
./run.sh (verified on the DragonFly audit guest β run.log; triggers exit 2:
/dev/dri absent β no radeon GPU on the QEMU guest, see env.txt)
Expected on r600/rv770 hardware
See VERDICT.md.
DF-4032 β r600 texture mipmap BO bounds check is commented out (GPU OOB mip walk)
File: sys/dev/drm/radeon/r600_cs.c
Severity: Medium (cross-process GPU memory disclosure via texture sampling; hardware-gated)
Root cause (path:line)
r600_check_texture_resource() computes the mipmap chain size with
r600_texture_size() (r600_cs.c:1399-1457) and then... does nothing:
1602: /* using get ib will give us the offset into the mipmap bo */
1603: if ((mipmap_size + word3) > radeon_bo_size(mipmap)) {
1604: /*dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n",
1605: w0, h0, format, blevel, nlevels, word3, mipmap_size, radeon_bo_size(texture));*/
1606: }
1607: return 0;
The check body is commented out, so any texture resource is accepted regardless of the
mipmap BO size. word3 (the user's mip offset) and mipmap_size (derived from
LAST_LEVEL/BASE_LEVEL/width/height/format) are otherwise unbounded (the l0_size check at
:1594 covers only level-0 in the texture BO).
The GPU texture unit then walks mip levels past the end of the mipmap BO: sampling the texture in a subsequent draw reads adjacent GPU memory (other processes' BOs / GTT pages), and the sampled values can be rendered into an attacker-owned target β a cross-process info-leak. The PoC geometry (512x512 R8, 10 levels, 256-byte mipmap BO) walks 87,125 bytes past the BO (texmip_sim, run.log).
The size accumulation itself is also u32 (offset += size in r600_texture_size:1450), so
even a restored check must be u64-safe β the proposed fix in fix.diff restores it with
(u64) casts.
Upstream status
The commented-out check is identical in current Linux master (upstream
r600_cs.c:1603-1609 β "don't break userspace" heritage). Unfixed upstream.
Verification (this pack)
texmip_sim.cβ replicatesr600_mip_minify/r600_texture_sizefor the PoC resource and prints the per-level offsets: mipmap_size 87,381 bytes vs a 256-byte mipmap BO (run.log, executed on the guest).r600_cs_poc.cmodetexmipβ SET_RESOURCE VALID_TEXTURE submission with the two relocs (texture BO 1 MiB, mipmap BO 256 B) exactly as the parser expects; builds clean on the guest.- Runtime hardware-gated (no radeon GPU on the audit guest β env.txt).
Suggested fix
fix.diff: restore the check with 64-bit arithmetic and reject oversized mipmap
requirements.
Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
Fix verification
not_testablefix.diff authored against the read-only sys/ tree after source verification; baseline and patched runs require r600/rv770 hardware which the audit guest lacks, so fix validation is not testable here.
fix.diff in this pack
Confirmed kernel references
Detail
Exploit chain
Unpriv CS with 512x512 R8 texture, 10 mip levels, 256-byte mipmap BO -> sampler reads OOB GPU memory -> draw renders leaked texels into attacker BO.
Evidence (decisive lines)
VERDICT.md (full path:line trace); run.log (guest trigger run + arithmetic simulation proving the validator math line-exact); build.log (clean guest build); env.txt (guest has no radeon GPU β hardware-gated); fix.diff (proposed fix, NOT applied to sys/)
PoC changes
Trigger written from scratch for this pack (raw ioctl, no libdrm, self-contained struct defs); arithmetic sims written to verify each wrap/desync claim line-exact; past-IB hypothesis for DF-4029 explicitly tested and killed by resource_index_sim.
Verified recommended fix
Restore the check with u64 arithmetic (see fix.diff).
Verdict
r600_check_texture_resource's mipmap BO bounds check is commented out (r600_cs.c:1603-1606): any LAST_LEVEL/BASE_LEVEL/word3 mip offset is accepted regardless of mipmap BO size. texmip_sim (run.log) shows the PoC resource walks 87,125 bytes past a 256-byte mipmap BO -> GPU texture sampler reads adjacent GPU memory -> cross-process info leak via rendered samples. Hardware-gated: no radeon GPU on the audit guest.
No comments yet.