Unclamped VBIOS SCLK DPM count overflows GraphicsLevel[8] in vegam_populate_all_graphic_levels (heap OOB write past vegam_smumgr)
Summary
The walk writes smc_state_table.GraphicsLevel[i] with no clamp against SMU75_MAX_LEVELS_GRAPHICS=8; count is the VBIOS u8 ucNumEntries copied 1:1 with no clamp anywhere in the chain. Guest-probe-proven sizes: GraphicsLevel=60B, capacity 480B inside the 1956B DpmTable in the kzalloc'd vegam_smumgr. count=9 already OOB; count=255 writes 15,300B (~13KB past the entire allocation). Crafted-vBIOS VegaM heap corruption. Clamp fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4069 Β· 8 files| File | Type | Description | Size | |
|---|---|---|---|---|
| probe.c | β | 2.5 KB | view raw | |
| build.log | β | 28 B | view raw | |
| run.log | β | 792 B | view raw | |
| verdict.json | β | 2.5 KB | view raw | |
| README.md | β | 585 B | β raw | |
| VERDICT.md | β | 2.0 KB | β raw | |
| fix.diff | β | 809 B | view raw | |
| manifest.json | β | 921 B | view raw |
DF-4069 β vegam SCLK GraphicsLevel heap OOB write (pass 2)
File: sys/dev/drm/amd/powerplay/smumgr/vegam_smumgr.c:886-913 (loops at 911-913, 920-922)
Build (guest, struct probe only β no GPU needed): cd /tmp && cc -I/usr/src/sys/dev/drm/amd/powerplay/inc -o probe probe.c Run: ./probe Expected: prints exact capacities proving the overflow arithmetic (GraphicsLevel=60B, capacity 8*60=480B; count=255 -> 15300B walk). Full trigger requires a VegaM GPU + crafted VBIOS powerplay table (absent on guest). Hardware-gated: verdict = inconclusive / source-level certain.
DF-4069 VERDICT β source-level certain, hardware-gated (not reproducible on audit guest)
Root cause (path:line)
vegam_populate_all_graphic_levels()loopsfor (i = 0; i < dpm_table->sclk_table.count; i++)writingsmc_state_table.GraphicsLevel[i]β vegam_smumgr.c:886-901, second pass 911-913 and 920-922.- Destination:
SMU75_Discrete_GraphicsLevel GraphicsLevel[SMU75_MAX_LEVELS_GRAPHICS=8]β smu75_discrete.h:287 (offset 236 in the 1956-byte SMU75_Discrete_DpmTable, member of kzalloc'dstruct vegam_smumgr, vegam_smumgr.h:66). - Count provenance: VBIOS
ucNumEntries(u8) β process_pptables_v1_0.c:425-470 (asserted !=0 only), copied 1:1 intodpm_table.sclk_table.countby smu7_hwmgr.c:689-697 / 783-810 (count++ per distinct clk, NO clamp). Nothing between the parser and this loop clamps to 8.
Proof (guest-compiled probe, exact numbers from the in-tree headers; run.log)
- sizeof(SMU75_Discrete_GraphicsLevel) = 60 β capacity 480 B.
- count=9 β first OOB write (offset 236+540 = 776, into MemoryACPILevel).
- count=255 β 255*60 = 15,300 B from offset 236 β ends ~13 KB past the entire vegam_smumgr heap object (slab-adjacent overwrite; writes are SMU register constants + VBIOS-derived fields).
Why not reproduced
Audit guest has no AMD VegaM GPU; the DRM powerplay path cannot execute. Per honest-status table this is hardware-gated: status=inconclusive, impact=none, confidence=certain (source).
Negative checks done
GraphicsDpmLevelCount = (uint8_t)count(:906) β no truncation possible (count is u8-sourced).- Not covered by knowns: DF-1366/67/68 = VCE/UVD/CAC/clock-stretcher/AVFS walks only.
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_testableHardware-gated finding (no AMD VegaM GPU / no LSI mps controller on the audit guest): fix authored at source level (fix.diff) but not build/boot-validated.
fix.diff in this pack; authored post-analysis, not hardware-validated.
Confirmed kernel references
Detail
Evidence (decisive lines)
probe.c + run.log: sizeof(SMU75_Discrete_GraphicsLevel)=60, capacity=8*60=480B, count=255 -> 15300B; smu75_discrete.h:287; vegam_smumgr.c:886-913,920-922
PoC changes
n/a (source-level analysis; struct probe written fresh, compiled on guest)
Verified recommended fix
Clamp the SCLK level walk (and both follow-up loops + GraphicsDpmLevelCount) to SMU75_MAX_LEVELS_GRAPHICS.
Verdict
Source-level certain, hardware-gated. vegam_populate_all_graphic_levels() walks dpm_table.sclk_table.count (VBIOS u8 ucNumEntries, unclamped anywhere on the path process_pptables_v1_0.c -> smu7_hwmgr.c -> here) writing GraphicsLevel[i] into a fixed array of SMU75_MAX_LEVELS_GRAPHICS=8 entries (60B each, 480B capacity, offset 236 in the 1956B SMU75_Discrete_DpmTable embedded in kzalloc'd vegam_smumgr). count=9 is already OOB (into MemoryACPILevel/MemoryLevel); count=255 writes 15,300B from the array start => ~13KB past the entire heap allocation. Sizes proven by a guest-compiled probe against the in-tree headers (run.log). Not runnable on the audit guest: requires a VegaM (AMDGPU_FAMILY_AI polaris-class vegam SKU) GPU fed a crafted powerplay table.
No comments yet.