Heap OOB write in phm_get_svi2_voltage_table_v0: VBIOS V0 dependency count (u8, up to 255) copied into fixed entries[32] before any trim
Summary
smu7's local V0 SVI2 constructor copies voltage_dependency_table->count entries into voltage_table->entries[PP_ATOMCTRL_MAX_VOLTAGE_ENTRIES=32]; the V0 count is the raw VBIOS ucNumEntries (u8, unvalidated). With count>32 the loop writes up to 1784 bytes past entries[31], corrupting the adjacent vddci/mvdd/vddgfx tables and following members of the heap-allocated struct smu7_hwmgr. The 'trim' runs after construction and only clamps the count field. HARNESS-VERIFIED on the guest (verbatim kernel function + 1:1 struct layouts, canary-guarded adjacency): 'out-of-bounds entry writes observed: 223', vddci count corrupted to 632, canaries smashed with the crafted mV values. smu7 twin of DF-3585/DF-3619/DF-3644; V1 twin is DF-1797 (smu_helper.c). Crafted VBIOS (physical flash / VFIO passthrough / root sysfs pp_table) on a V0 SMU7 board (CI, Topaz).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3683 Β· 11 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.5 KB | β raw | |
| VERDICT.md | β | 3.6 KB | β raw | |
| svi2_v0_overflow.c | β | 4.7 KB | view raw | |
| build.sh | β | 110 B | view raw | |
| run.sh | β | 154 B | view raw | |
| build.log | β | 376 B | view raw | |
| run.log | β | 1.4 KB | view raw | |
| env.txt | β | 1.1 KB | view raw | |
| fix.diff | β | 748 B | view raw | |
| verdict.json | β | 3.7 KB | view raw | |
| manifest.json | β | 1.1 KB | view raw |
DF-3683 β Heap OOB write in phm_get_svi2_voltage_table_v0: VBIOS V0 dependency count (u8, up to 255) copied into fixed entries[32] before any trim
File: sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c (pass 2, GLM 5.3 re-audit)
Severity: High | CVSS: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H | CWE: CWE-787 Out-of-bounds Write | Confidence: certain (source)
What this is
Source-certain heap OOB write; runtime-inconclusive on this guest (no AMD GPU). phm_get_svi2_voltage_table_v0 (smu7_hwmgr.c:219-239, defined only in this file) copies voltage_dependency_table->count entries into voltage_table->entries[PP_ATOMCTRL_MAX_VOLTAGE_ENTRIES=32] (ppatomctrl.h:45,211). For V0 boards the count is the raw VBIOS ucNumEntries (u8, 1..255, no upper bound: processpptables.c:375-404), and the call sites (smu7_hwmgr.c:265-268 MVDD, :285-289 VDDCI, :313-317 VDDC) pass dyn_state.{mvdd,vddci,vddc}_dependency_on_mclk. The 'trimming' at :323-349 runs AFTER construction and only clamps the count field - it cannot undo the writes. With count=255 the loop writes 223 entries (1784 bytes) past entries[31], clobbering the adjacent vddci/mvdd/vddgfx voltage tables and the following members of the heap-allocated struct smu7_hwmgr (smu7_hwmgr.h:250-254). Precondition: crafted VBIOS (or VFIO/root sysfs pp_table) declaring SVID2 voltage control (atomctrl_is_voltage_controlled_by_gpio_v3) plus a dependency table with >32 entries. smu7 twin of DF-3585/DF-3619/DF-3644 (si/ci); the V1 twin of the same construction lives in smu_helper.c (DF-1797). Harness (verbatim function, real struct layouts) confirmed 223 forged OOB writes with VBIOS-controlled u16 voltage values corrupting canaries modelling the adjacent backend fields.
Reproduce (harness on the audit QEMU guest)
scp -F dfbsd-qemu/config svi2_v0_overflow.c dfbsd-maxx:/tmp/DF-3683/ ssh -F dfbsd-qemu/config dfbsd-maxx 'cd /tmp/DF-3683 && cc -Wall -O0 -o t svi2_v0_overflow.c && ./t'
Expected: the run prints the confirmed-primitive line (RESULT: ... CONFIRMED ...).
See run.log (and run.2.log where present) for the decisive captured output,
build.log for the guest toolchain transcript, env.txt for the guest environment
(virtio-only, no AMD GPU β pciconf -l shows only 0x1237/0x1111 QEMU devices;
drm.ko/amdgpu.ko exist in /boot/kernel but are not loaded and have no hardware
to bind), which is why the in-kernel trigger itself is inconclusive on this guest.
Fix
fix.diff (authored against the read-only sys/ tree; never applied there).
DF-3683 β verdict narrative
Finding
Source-certain heap OOB write; runtime-inconclusive on this guest (no AMD GPU). phm_get_svi2_voltage_table_v0 (smu7_hwmgr.c:219-239, defined only in this file) copies voltage_dependency_table->count entries into voltage_table->entries[PP_ATOMCTRL_MAX_VOLTAGE_ENTRIES=32] (ppatomctrl.h:45,211). For V0 boards the count is the raw VBIOS ucNumEntries (u8, 1..255, no upper bound: processpptables.c:375-404), and the call sites (smu7_hwmgr.c:265-268 MVDD, :285-289 VDDCI, :313-317 VDDC) pass dyn_state.{mvdd,vddci,vddc}_dependency_on_mclk. The 'trimming' at :323-349 runs AFTER construction and only clamps the count field - it cannot undo the writes. With count=255 the loop writes 223 entries (1784 bytes) past entries[31], clobbering the adjacent vddci/mvdd/vddgfx voltage tables and the following members of the heap-allocated struct smu7_hwmgr (smu7_hwmgr.h:250-254). Precondition: crafted VBIOS (or VFIO/root sysfs pp_table) declaring SVID2 voltage control (atomctrl_is_voltage_controlled_by_gpio_v3) plus a dependency table with >32 entries. smu7 twin of DF-3585/DF-3619/DF-3644 (si/ci); the V1 twin of the same construction lives in smu_helper.c (DF-1797). Harness (verbatim function, real struct layouts) confirmed 223 forged OOB writes with VBIOS-controlled u16 voltage values corrupting canaries modelling the adjacent backend fields.
Root cause (kernel references)
sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c:219sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c:232sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c:263sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c:313sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c:323sys/dev/drm/amd/powerplay/hwmgr/ppatomctrl.h:45sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.h:250sys/dev/drm/amd/powerplay/hwmgr/processpptables.c:391
What was verified, and how
- Source-level certainty. Full-file pass-2 audit of smu7_hwmgr.c (5147 lines) with the parse-side preconditions traced into processpptables.c / process_pptables_v1_0.c (VBIOS u8 counts unvalidated; offset==0 subtables parse-legal NULL) and the struct geometry verified in ppatomctrl.h / smu7_hwmgr.h / hardwaremanager.h / dm_pp_interface.h.
- Harness on the guest (DragonFly 6.5-DEVELOPMENT x86_64,
ccbase toolchain):svi2_v0_overflow.creproduces the exact kernel code shape and/or arithmetic with 1:1 struct layouts. Output inrun.log. Compiled with-O0β at-O2the compiler detects the array-index UB and misoptimizes the accounting loops (itself a hint of what the kernel code does). - Hardware absence. The guest is virtio-only: no AMD GPU on PCI, amdgpu not loaded. The in-kernel trigger requires an SMU7 ASIC (CI/Topaz/Tonga/Fiji/Polaris/ Vegam) with a crafted VBIOS, VFIO passthrough of a malicious card, or a root sysfs pp_table write. Per pass-2 spawn instructions this is recorded as inconclusive (matching DF-3585/DF-3619/DF-3644 precedent for the same class), impact none on this guest.
Fix validation
fix.diff authored post-verification against the read-only sys/ tree. Not built: a
kernel rebuild with drm cannot be exercised on a GPU-less guest, so fix validation is
not_testable; the diffs are minimal, local, and mechanically checkable against the
cited lines.
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+harness verification; not built (no AMD hardware on guest).
findings/poc/DF-3683/fix.diff
Confirmed kernel references
- sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c:219
- sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c:232
- sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c:263
- sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c:313
- sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c:323
- sys/dev/drm/amd/powerplay/hwmgr/ppatomctrl.h:45
- sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.h:250
- sys/dev/drm/amd/powerplay/hwmgr/processpptables.c:391
Detail
Evidence (decisive lines)
run.log: 'out-of-bounds entry writes observed: 223', 'vddci_voltage_table.count corrupted: 632', 'canary[0] CORRUPTED: 0xa5a502dd' (the crafted 600+i mV values visible in the smashed words); VERDICT.md; fix.diff (clamp count to PP_ATOMCTRL_MAX_VOLTAGE_ENTRIES before the loop)
PoC changes
Seed had no runnable PoC; wrote a faithful unit harness (verbatim kernel function + 1:1 struct layouts from ppatomctrl.h/smu7_hwmgr.h with canary-guarded adjacency) since the real trigger requires an AMD SMU7 ASIC with a crafted VBIOS.
Verified recommended fix
Clamp voltage_dependency_table->count to PP_ATOMCTRL_MAX_VOLTAGE_ENTRIES before the copy loop in phm_get_svi2_voltage_table_v0 (and fail loudly), mirroring the trim that already happens too late at smu7_hwmgr.c:323-349.
Verdict
Source-certain heap OOB write; runtime-inconclusive on this guest (no AMD GPU). phm_get_svi2_voltage_table_v0 (smu7_hwmgr.c:219-239, defined only in this file) copies voltage_dependency_table->count entries into voltage_table->entries[PP_ATOMCTRL_MAX_VOLTAGE_ENTRIES=32] (ppatomctrl.h:45,211). For V0 boards the count is the raw VBIOS ucNumEntries (u8, 1..255, no upper bound: processpptables.c:375-404), and the call sites (smu7_hwmgr.c:265-268 MVDD, :285-289 VDDCI, :313-317 VDDC) pass dyn_state.{mvdd,vddci,vddc}_dependency_on_mclk. The 'trimming' at :323-349 runs AFTER construction and only clamps the count field - it cannot undo the writes. With count=255 the loop writes 223 entries (1784 bytes) past entries[31], clobbering the adjacent vddci/mvdd/vddgfx voltage tables and the following members of the heap-allocated struct smu7_hwmgr (smu7_hwmgr.h:250-254). Precondition: crafted VBIOS (or VFIO/root sysfs pp_table) declaring SVID2 voltage control (atomctrl_is_voltage_controlled_by_gpio_v3) plus a dependency table with >32 entries. smu7 twin of DF-3585/DF-3619/DF-3644 (si/ci); the V1 twin of the same construction lives in smu_helper.c (DF-1797). Harness (verbatim function, real struct layouts) confirmed 223 forged OOB writes with VBIOS-controlled u16 voltage values corrupting canaries modelling the adjacent backend fields.
No comments yet.