Heap+stack OOB writes in clock-stretcher/AVFS/CAC table population via unbounded VBIOS counts
Summary
vegam_populate_cac_table :515: lookup_table->count drives BapmVddcVid*[SMU75_MAX_LEVELS_VDDC=16] writes. vegam_populate_clock_stretcher_data_table :1515: sclk_table->count drives Sclk_voltageOffset[8] heap OOB. vegam_populate_avfs_parameters :1636: sclk_table->count drives Static_Voltage_Offset[8] and Sclk_Offset[8] STACK OOB (local structs -> return addr corruption). All counts from VBIOS ucNumEntries unclamped. Crafted VBIOS. Fix: clamp each loop to destination array size.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1368 Β· 9 files| File | Type | Description | Size | |
|---|---|---|---|---|
| fix.diff | suggested-fix | git-apply-able fix; compile-validated under -Werror in the amdgpu build | 1.4 KB | view raw |
| VERDICT.md | verdict | full source trace + reachability analysis + compile-validation | 3.3 KB | β raw |
| README.md | readme | summary, mechanism, trigger conditions, fix | 3.3 KB | β raw |
| build.sh | build | script that applies fix.diff and rebuilds the amdgpu | 383 B | view raw |
| run.sh | run | guest reachability probe | 658 B | view raw |
| build_fix.log | build-log | build log slice showing the patched file compiles cleanly (rc=0) | 118 B | view raw |
| env.txt | environment | uname, cc, PCI/kldstat/device-node state proving no HW | 1.4 KB | 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-1368 -- Heap+stack OOB in vegam CAC/clock_stretcher/AVFS (unclamped counts)
File: sys/dev/drm/amd/powerplay/smumgr/vegam_smumgr.c:515
Class: memory corruption (heap OOB / OOB write / OOB read)
Status: INCONCLUSIVE at runtime -- CONFIRMED source bug, hardware-gated on this guest
The vulnerable code path was traced line-by-line in sys/ and confirmed to be a
genuine bug (missing bounds check / integer overflow / unvalidated HBA-supplied
index). However it is not exercisable on the DragonFly audit guest because the
guest has no amdgpu hardware:
- PCI shows only QEMU stdvga (
vgapci0 class=0x030000 chip=0x11111234), virtio_net and virtio_blk -- no AMD GPU, no Intel iGPU, no LSI SAS HBA, no floppy controller, no TI ThunderLAN NIC, no Emulex OneConnect NIC, no BusLogic SCSI HBA. - The amdgpu driver (whether a loadable .ko or compiled-in) never attaches.
/dev/fd0,/dev/dri,/dev/dsp*do not exist on this guest.
This is the valid hard-blocker "vulnerable code path unreachable at runtime on this guest AND no harness can exercise it" -- the bug is a real latent defect that would manifest on a system with the relevant hardware (or, for VBIOS-driven bugs, a crafted VBIOS via passthrough/hotplug).
Mechanism (confirmed by source trace)
Three independent unclamped loops, all driven by VBIOS counts, writing fixed-size arrays: * vegam_populate_cac_table :515 -- count from lookup_table->count writes BapmVddcVidLoSidd/HiSidd/HiSidd2[count], each [SMU75_MAX_LEVELS_VDDC=16]. * vegam_populate_clock_stretcher_data_table :1515 -- sclk_table->count writes smc_state_table.Sclk_voltageOffset[i] (heap OOB, array [8]). * vegam_populate_avfs_parameters :1636 -- sclk_table->count writes AVFS_meanNsigma.Static_Voltage_Offset[i] and AVFS_SclkOffset.Sclk_Offset[i] (both stack-local structs of size [8] -> return-address corruption). All counts come from VBIOS ucNumEntries unclamped.
Live trigger conditions
Requires the amdgpu hardware (and the driver loaded). For VBIOS-driven bugs, requires a crafted VBIOS via PCI passthrough or hotplug. The audit QEMU guest has none of this hardware, so the bug is unreachable here.
Fix
A standalone, git apply-able fix is in fix.diff. Compile-validated: applied
to in-guest /usr/src and built with the kernel's -Werror flags (rc=0, no
warnings/errors in the patched translation unit). See build_fix.log.
Added && count < SMU75_MAX_LEVELS_VDDC to the CAC loop and && i <
NUM_VFT_COLUMNS (=8) to both the clock_stretcher and AVFS loops. (matches
finding proposal: clamp each loop to destination array size.)
Reproduce / validate
# 1. Confirm the bug site (read-only source trace): grep -n ... sys/dev/drm/amd/powerplay/smumgr/vegam_smumgr.c # 2. Compile-validate the fix on the audit guest: scp -F dfbsd-qemu/config findings/poc/DF-1368/fix.diff dfbsd:/root/DF-1368.fix.diff ./dfbsd-qemu/vm.sh run_root 'cd /usr/src && patch -p1 --forward < /root/DF-1368.fix.diff' # Then either: # cd /usr/src && make -j6 nativekernel KERNCONF=X86_64_GENERIC # kernel-internal drivers # OR # cd /usr/src/sys/dev/drm/<module> && KERNCONF=X86_64_GENERIC SYSDIR=/usr/src/sys make -m /usr/src/share/mk # GPU modules # 3. (requires real hardware) Exercise the bug: attach the HW and trigger.
VERDICT -- DF-1368
Verdict: INCONCLUSIVE at runtime; source bug CONFIRMED; fix COMPILE-VALIDATED
Citations confirmed: - sys/dev/drm/amd/powerplay/smumgr/vegam_smumgr.c:515 - sys/dev/drm/amd/powerplay/smumgr/vegam_smumgr.c:1515 - sys/dev/drm/amd/powerplay/smumgr/vegam_smumgr.c:1636 - sys/dev/drm/amd/powerplay/smumgr/vegam_smumgr.c:1637 - sys/dev/drm/amd/powerplay/smumgr/vegam_smumgr.c:1639
Is the bug real? -- YES (source trace)
Three independent unclamped loops, all driven by VBIOS counts, writing fixed-size arrays: * vegam_populate_cac_table :515 -- count from lookup_table->count writes BapmVddcVidLoSidd/HiSidd/HiSidd2[count], each [SMU75_MAX_LEVELS_VDDC=16]. * vegam_populate_clock_stretcher_data_table :1515 -- sclk_table->count writes smc_state_table.Sclk_voltageOffset[i] (heap OOB, array [8]). * vegam_populate_avfs_parameters :1636 -- sclk_table->count writes AVFS_meanNsigma.Static_Voltage_Offset[i] and AVFS_SclkOffset.Sclk_Offset[i] (both stack-local structs of size [8] -> return-address corruption). All counts come from VBIOS ucNumEntries unclamped.
Can it be reproduced on this guest? -- NO (hardware-gated)
No AMD GPU in PCI list; amdgpu.ko not loaded.
The amdgpu driver is a loadable module only (NOT in X86_64_GENERIC), is not loaded, and cannot be kldload'd by an unprivileged user (kldload is root-only). Even loaded, it would not attach without the hardware.
Therefore the vulnerable code is unreachable at runtime here. Because the sinks are device-integrated parsers / DRM ioctls / DMA-supplied indices / hardware-dependent paths, no userspace harness on this guest can exercise them. This is the documented valid hard-blocker "unreachable at runtime + no feasible harness"; the bug is a real latent defect with the live trigger conditions noted above.
No escalation chain (and why that is correct here)
There is no memory-corruption primitive to escalate on this guest: the corruption sinks live entirely inside the not-attached driver behind hardware that is absent. The escalation work the audit expects (slab groom -> victim -> uid0) presupposes a reachable write primitive; here there is none on the guest. The deliverable is therefore the confirmed root-cause + a compile-validated fix.
Fix (fix.diff) -- authored and COMPILE-VALIDATED
Added && count < SMU75_MAX_LEVELS_VDDC to the CAC loop and && i <
NUM_VFT_COLUMNS (=8) to both the clock_stretcher and AVFS loops. (matches
finding proposal: clamp each loop to destination array size.)
The fix was applied to in-guest /usr/src (all hunks applied cleanly) and the
module was rebuilt with the kernel's -Werror flags: cd /usr/src/sys/dev/drm/amdgpu && KERNCONF=X86_64_GENERIC SYSDIR=/usr/src/sys make -m /usr/src/share/mk => rc=0 (see build_fix.log). No warnings or errors in the patched translation unit. The runtime before/after of the bug cannot be tested on this guest (no hardware), so fix_status is not_testable (diff applies + compiles; code path traced closed).
Why not not_reproduced (false-positive)?
This is NOT a false positive. The cited sys/ code is genuinely missing the guard / has the overflow / has the unclamped loop -- verified by reading the source. It is a real bug that is simply out of reach of this particular (driverless) QEMU guest.
Confirmed kernel references
- s
- y
- s
- /
- d
- e
- v
- /
- d
- r
- m
- /
- a
- m
- d
- /
- p
- o
- w
- e
- r
- p
- l
- a
- y
- /
- s
- m
- u
- m
- g
- r
- /
- v
- e
- g
- a
- m
- _
- s
- m
- u
- m
- g
- r
- .
- c
- :
- 5
- 1
- 5
- s
- y
- s
- /
- d
- e
- v
- /
- d
- r
- m
- /
- a
- m
- d
- /
- p
- o
- w
- e
- r
- p
- l
- a
- y
- /
- s
- m
- u
- m
- g
- r
- /
- v
- e
- g
- a
- m
- _
- s
- m
- u
- m
- g
- r
- .
- c
- :
- 1
- 5
- 1
- 5
- s
- y
- s
- /
- d
- e
- v
- /
- d
- r
- m
- /
- a
- m
- d
- /
- p
- o
- w
- e
- r
- p
- l
- a
- y
- /
- s
- m
- u
- m
- g
- r
- /
- v
- e
- g
- a
- m
- _
- s
- m
- u
- m
- g
- r
- .
- c
- :
- 1
- 6
- 3
- 6
- s
- y
- s
- /
- d
- e
- v
- /
- d
- r
- m
- /
- a
- m
- d
- /
- p
- o
- w
- e
- r
- p
- l
- a
- y
- /
- i
- n
- c
- /
- s
- m
- u
- 7
- 5
- .
- h
- :
- 4
- 8
- s
- y
- s
- /
- d
- e
- v
- /
- d
- r
- m
- /
- a
- m
- d
- /
- p
- o
- w
- e
- r
- p
- l
- a
- y
- /
- i
- n
- c
- /
- s
- m
- u
- 7
- 5
- .
- h
- :
- 6
- 4
- 0
- s
- y
- s
- /
- d
- e
- v
- /
- d
- r
- m
- /
- a
- m
- d
- /
- p
- o
- w
- e
- r
- p
- l
- a
- y
- /
- i
- n
- c
- /
- s
- m
- u
- 7
- 5
- .
- h
- :
- 7
- 4
- 0
- s
- y
- s
- /
- d
- e
- v
- /
- d
- r
- m
- /
- a
- m
- d
- /
- p
- o
- w
- e
- r
- p
- l
- a
- y
- /
- i
- n
- c
- /
- s
- m
- u
- 7
- 5
- .
- h
- :
- 7
- 4
- 5
Detail
Exploit chain
none (not a memory-corruption primitive on this guest): amdgpu driver not attached (no HW).
Evidence (decisive lines)
Source trace: vegam_smumgr.c:515,1515,1636 + smu75.h:48,256-258,640-650,740,745 confirmed. Guest PCI: only QEMU stdvga. Fix compile-validated (3 hunks): amdgpu module rc=0 under -Werror.
PoC changes
Wrote fresh evidence pack under findings/poc/DF-1368/ plus git-apply-able fix.diff with 3 hunks: CAC loop gets && count < SMU75_MAX_LEVELS_VDDC; clock_stretcher and AVFS loops get && i < NUM_VFT_COLUMNS.
Verified recommended fix
Add && count < SMU75_MAX_LEVELS_VDDC to the CAC loop condition at :515; add && i < NUM_VFT_COLUMNS to the clock_stretcher loop at :1515 and the AVFS loop at :1636. matches finding proposal.
Verdict
Source-confirmed (3 hunks). (1) vegam_populate_cac_table() at vegam_smumgr.c:515 loops count
No comments yet.