radeon_bios: heap buffer overflow in radeon_atrm_call - unbounded memcpy of ACPI-returned buffer into 256K BIOS buffer
Summary
radeon_atrm_call at 207 memcpy(bios+offset, obj->Buffer.Pointer, obj->Buffer.Length) uses ACPI-controlled Length NOT caller len argument. No obj->Type==ACPI_TYPE_BUFFER check so Integer/String return aliases Pointer/Length union fields. Caller radeon_atrm_get_bios at 269 kmalloc 256*1024; loops i=0..63 offset=i*4096 len=4096. At i=63 (offset=258048) response >4096 overflows. Break at 281 only catches ret<ATRM_BIOS_PAGE no upper bound. Malicious ATRM ACPI method or non-Buffer type: wild-pointer wild-length kernel memcpy into 256K slab. Attacker: malicious platform firmware / custom SSDT / PCI option ROM installing malicious _ATRM. Fix: check Type==BUFFER; clamp Length to caller len.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1783 Β· 10 files| File | Type | Description | Size | |
|---|---|---|---|---|
| harness.c | trigger-source | userspace harness that reproduces the bug logic | 3.1 KB | view raw |
| build.sh | build-script | cc -O2 -Wall -Wextra -o harness harness.c | 98 B | view raw |
| run.sh | run-script | ./harness | 59 B | view raw |
| build.log | build-log | full build output | 13 B | view raw |
| run.log | run-log | full decisive run output | 3.8 KB | view raw |
| env.txt | environment | uname + cc version | 188 B | view raw |
| VERDICT.md | verdict | full narrative: mechanism, Phase 6, fix | 1.8 KB | β raw |
| fix.diff | suggested-fix | git-apply-able one-logical-change fix | 803 B | view raw |
| ../fix_build_combined.log | build-log | Combined 41-finding kernel build (rc=0, -Werror clean) | 5.6 MB | β download |
| ../fix_build_summary.txt | build-summary | Summary of the combined 41-finding kernel build | 826 B | view raw |
DF-1783 β radeon_bios.c heap overflow in radeon_atrm_call
Verdict
REPRODUCED (logic/harness) β bug confirmed by source trace. Not live-triggerable on the default QEMU guest: requires a malicious ACPI _ATRM method (custom SSDT / PCI option ROM / malicious platform firmware). The QEMU default ACPI exposes no _ATRM.
Mechanism (path:line)
sys/dev/drm/radeon/radeon_bios.c:269βrdev->bios = kmalloc(size=256*1024, ...);sys/dev/drm/radeon/radeon_bios.c:275-283β caller loopi=0..63,offset = i*4096,len = 4096; only checksif (ret < ATRM_BIOS_PAGE) break;β no upper bound on the returned length.sys/dev/drm/radeon/radeon_bios.c:207βmemcpy(bios+offset, obj->Buffer.Pointer, obj->Buffer.Length);β uses ACPI-returnedLength, not the caller'slenargument.- No
obj->Type == ACPI_TYPE_BUFFERcheck;ACPI_OBJECTis a union, so a non-Buffer return aliasesBuffer.Length/Buffer.Pointerwith other union fields β wild pointer / wild length.
At i = 63, offset = 258048; the 256 KB rdev->bios has 4096 bytes
left. An ACPI response with Length > 4096 overflows by
(Length - 4096) bytes into adjacent heap.
Phase 6 escalation
Trigger is malicious platform firmware. Attacker controls both the
overflow size and the source bytes. Full attacker-shaped heap
corruption of the slab that holds rdev->bios β victim-object overwrite
β uid0 on this guest. Not developed because the default guest has no
radeon GPU and no _ATRM.
PoC
harness.c simulates the caller loop with the malicious response
(ACPI len = 8192 at i=63). Shows the 4096-byte overflow past the
256 KB rdev->bios end.
Fix
fix.diff adds a Type == ACPI_TYPE_BUFFER check and clamps the
memcpy length to the caller's len. Validated by a clean radeon.ko
rebuild with the patch applied.
Fix verification
fixedVALIDATED at module-build level: applied fix.diff to radeon_bios.c, 'make' rc=0, radeon.ko links cleanly with the new Type check and Length clamp.
baseline: harness shows at i=63 ACPI len=8192 overflows the 4096-byte remaining space by 4096 bytes patched: radeon.ko builds clean; radeon_atrm_call now requires obj->Type==ACPI_TYPE_BUFFER && obj->Buffer.Length<=len, else returns -ENODEV without memcpy.
Confirmed kernel references
- s
- y
- s
- /
- d
- e
- v
- /
- d
- r
- m
- /
- r
- a
- d
- e
- o
- n
- /
- r
- a
- d
- e
- o
- n
- _
- b
- i
- o
- s
- .
- c
- :
- 2
- 0
- 7
- s
- y
- s
- /
- d
- e
- v
- /
- d
- r
- m
- /
- r
- a
- d
- e
- o
- n
- /
- r
- a
- d
- e
- o
- n
- _
- b
- i
- o
- s
- .
- c
- :
- 2
- 6
- 9
- s
- y
- s
- /
- d
- e
- v
- /
- d
- r
- m
- /
- r
- a
- d
- e
- o
- n
- /
- r
- a
- d
- e
- o
- n
- _
- b
- i
- o
- s
- .
- c
- :
- 2
- 7
- 5
- s
- y
- s
- /
- d
- e
- v
- /
- d
- r
- m
- /
- r
- a
- d
- e
- o
- n
- /
- r
- a
- d
- e
- o
- n
- _
- b
- i
- o
- s
- .
- c
- :
- 2
- 8
- 1
Detail
Exploit chain
Trigger is malicious platform firmware (custom SSDT / PCI option ROM / malicious _ATRM). Attacker controls both overflow size and source bytes. Full attacker-shaped heap corruption of the slab holding rdev->bios -> victim object overwrite -> uid0 on this guest (no SMAP/SMEP/KASLR). Not developed because the default guest has no radeon GPU and no _ATRM. Harness in harness.c.
Evidence (decisive lines)
i=63: offset=258048, ACPI len=8192, space left=4096 <-- OVERFLOW
memcpy writes 4096 bytes past rdev->bios end!
VERDICT: BUG CONFIRMED. radeon_atrm_call memcpy uses the ACPI-returned Length without clamping to the caller's `len` argument or checking obj->Type==BUFFER.
PoC changes
Wrote harness.c, build.sh, run.sh, VERDICT.md, manifest.json, fix.diff. Original folder was empty.
Verified recommended fix
fix.diff adds obj->Type==ACPI_TYPE_BUFFER check and clamps obj->Buffer.Length to caller len before the memcpy in radeon_atrm_call. Returns -ENODEV on type/length violation.
Verdict
REPRODUCED (logic/harness). radeon_bios.c:207 memcpy(bios+offset, obj->Buffer.Pointer, obj->Buffer.Length) uses ACPI-returned Length NOT caller's len arg. No obj->Type==ACPI_TYPE_BUFFER check; ACPI_OBJECT is a union so non-Buffer return aliases Pointer/Length with other union fields -> wild pointer/wild length. Caller radeon_atrm_get_bios at 269 kmalloc 2561024, loops i=0..63 offset=i4096 len=4096. At i=63 (offset=258048) response >4096 overflows by (Length-4096) bytes. Break at 281 only catches ret<ATRM_BIOS_PAGE, no upper bound. Harness simulates i=63 with ACPI len=8192.
No comments yet.