smu_get_voltage_dependency_table_ppt_v1 copies VBIOS-controlled count records into callers' fixed entries[8] ODN tables β heap OOB write of struct smu7_hwmgr (up to 6916 attacker-controlled bytes)
Summary
The helper has no destination-size parameter and copies the raw VBIOS ucNumEntries (up to 255) x 28-byte records; the smu7 call sites cast fixed entries[MAX_REGULAR_DPM_NUMBER=8] tables embedded in the heap-allocated hwmgr struct - count>8 overflows into adjacent members, count=255 writes 6916 bytes past entries[7] and 6420 past the struct allocation with fully attacker-chosen record contents. Reachable at driver load with OverDrive enabled and via PP_OD_RESTORE_DEFAULT_TABLE. Novel vs DF-1166 (fires with <=8 distinct clocks - dedup site in bounds while the copy overflows) and DF-3703/1799 (different legs/aspects). Harness-verified on guest: 224 OOB bytes at count=16, 55/64 canaries smashed at 255; fix validated. Central-hub fix (clamp + capacity param) closes the whole family.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4665 Β· 11 files| File | Type | Description | Size | |
|---|---|---|---|---|
| smu7_odn_overflow.c | β | 10.4 KB | view raw | |
| smu7_odn_overflow_patched.c | β | 5.2 KB | view raw | |
| build.sh | β | 187 B | view raw | |
| run.sh | β | 90 B | view raw | |
| build.log | β | 0 B | β download | |
| run.log | β | 2.6 KB | view raw | |
| env.txt | β | 188 B | view raw | |
| VERDICT.md | β | 3.5 KB | β raw | |
| fix.diff | β | 3.2 KB | view raw | |
| manifest.json | β | 1.3 KB | view raw | |
| verdict.json | β | 4.2 KB | view raw |
DF-4665 β VERDICT
Status: reproduced (harness; no AMD GPU on the audit guest β methodology identical to DF-3683/DF-3686: verbatim kernel function + 1:1 struct layouts, canary-guarded adjacency, run on the DragonFly 6.5-DEVELOPMENT guest).
What was run
smu7_odn_overflow.c compiles the verbatim body of
smu_get_voltage_dependency_table_ppt_v1 (smu_helper.c:675-699) against 1:1
copies of the kernel struct layouts
(phm_ppt_v1_clock_voltage_dependency_record β 28 bytes, compiler-confirmed;
phm_odn_clock_levels, smu7_odn_clock_voltage_dependency_table with
entries[8], smu7_odn_dpm_table, and a struct smu7_hwmgr-prefix buffer
with a 64-word canary region standing in for the members after
odn_dpm_table).
Observations (run.log, guest cc 8.3, DF 6.5-DEVELOPMENT)
- count=16, 2 distinct clocks β the DF-1166 dedup loop appends only 2
dpm_levels(IN BOUNDS, the known finding does NOT fire), then the odn copy writes 16 Γ 28 = 448 bytes intoentries[8]: 224 bytes OOB,vdd_dependency_on_mclk.countcorrupted from 0 to 102500 (a VBIOS clk value). Proves this bug fires on inputs the filed siblings do not cover. - count=255, 2 distinct clocks β DF-1166 site still in bounds; odn copy
writes 6916 bytes past entries[7], of which 6420 bytes past the end
of the backend-shaped object; 55/64 canary words smashed;
odn_mclk_min_limit,min_vddc,max_vddcall overwritten with attacker-record contents. On the real kernel this is a linear heap overflow of thekzalloc'dstruct smu7_hwmgrwith fully VBIOS-controlled data, running into whatever slab object follows. - Control count=8 β no corruption (function behaves correctly when the source happens to be in range).
- Patched twin (fix.diff applied to the harness function, call site
passes
MAX_REGULAR_DPM_NUMBER): stored count clamped to 8, zero canary damage for count=16 and count=255 β fix validated.
Exploit chain (realistic ceiling)
Crafted VBIOS / VFIO pp_table write on an smu7 board (Tonga/Fiji/Polaris10/
VegaM) with OverDrive enabled β at driver load
smu7_setup_default_dpm_tables β smu7_odn_initial_default_setting β this
copy β controlled 28-byte-stride heap overflow inside/past struct smu7_hwmgr
β kernel heap corruption (adjacent slab objects; struct smu7_hwmgr is a
several-KB kmalloc). Grooming the slab neighbour of the hwmgr backend could
turn this into code execution; at minimum a deterministic kernel panic. The
audit guest has no AMD GPU, so the chain is demonstrated at the
primitive level (above), matching the methodology precedent of DF-3683.
Kernel references
- sys/dev/drm/amd/powerplay/hwmgr/smu_helper.c:675-699 (the unbounded copy)
- sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c:844-845,856-857 (smu7 call sites, entries[8] dest)
- sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c:962-968, 4844-4846 (reachability)
- sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.h:95,177-190 (MAX_REGULAR_DPM_NUMBER=8, odn tables)
- sys/dev/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c:436,468 (count = raw ucNumEntries)
- sys/dev/drm/amd/powerplay/hwmgr/vega10_hwmgr.c:318-323 (vega10 leg β DF-3703, not re-filed)
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
fixedPatched-twin harness (function carrying the fix.diff clamp, call site passing MAX_REGULAR_DPM_NUMBER) shows stored count clamped to 8, vdd_dependency_on_mclk intact, 0/64 canaries damaged for count=16 and count=255 β the out-of-bounds write is gone. Full kernel rebuild not performed: no AMD GPU exists on the audit guest, so the verbatim-function harness is the faithful validation surface (same methodology as DF-3683).
findings/poc/DF-4665/run.log 'patched twin' sections: 'FIX VALIDATED: no out-of-bounds writes with clamped copy' (count=16 and count=255).
Confirmed kernel references
Detail
Exploit chain
crafted VBIOS / VFIO pp_table / root sysfs pp_table on smu7 board (Tonga/Fiji/Polaris10/VegaM) with od_enabled -> smu7_setup_default_dpm_tables:967 -> smu7_odn_initial_default_setting -> smu_get_voltage_dependency_table_ppt_v1(dep_sclk_table, &odn_table->vdd_dependency_on_sclk) -> linear heap overflow inside and past struct smu7_hwmgr with fully attacker-controlled 28-byte records (up to 6916 bytes past entries[7]) -> kernel heap corruption of adjacent slab objects; deterministic panic at minimum, potential code execution with slab grooming.
Evidence (decisive lines)
findings/poc/DF-4665/run.log: baseline count=255 section shows 'OOB bytes past entries[7] : 6916', 'past end of backend-like object: 6420', 'canary words ... smashed: 55/64', 'OOB-WRITE CONFIRMED'; count=16/2-distinct section shows DF-1166 site IN BOUNDS while vdd_dependency_on_mclk.count is corrupted (novelty vs DF-1166); patched-twin sections show 'FIX VALIDATED'.
PoC changes
Seed harness authored fresh for this finding (no prior seed): verbatim smu_helper.c:675-699 body + 1:1 struct layouts from hwmgr_ppt.h/hardwaremanager.h/smu7_hwmgr.h; canary-guarded struct-smu7_hwmgr-prefix buffer; DF-1166 dedup site replicated first to prove the new bug fires where the known one does not.
Verified recommended fix
Pass destination capacity (max_entries) to smu_get_voltage_dependency_table_ppt_v1 and clamp the copy; callers pass MAX_REGULAR_DPM_NUMBER.
Verdict
Harness-verified on the DragonFly 6.5-DEVELOPMENT guest using the verbatim kernel function and 1:1 struct layouts (no AMD GPU on the audit guest; methodology identical to DF-3683/DF-3686): smu_get_voltage_dependency_table_ppt_v1 has no destination-size parameter and copies allowed_dep_table->count (raw VBIOS ucNumEntries, up to 255) 28-byte records into callers' fixed entries[MAX_REGULAR_DPM_NUMBER=8] tables. The smu7 call path (smu7_odn_initial_default_setting, reached at driver load with OverDrive enabled and via PP_OD_RESTORE_DEFAULT_TABLE sysfs) overflows struct smu7_hwmgr: with count=16 and only 2 distinct clocks the already-filed DF-1166 dedup site stays in bounds while this copy writes 224 attacker-controlled bytes OOB (vdd_dependency_on_mclk.count corrupted to a VBIOS clk value); with count=255 it writes 6916 bytes past entries[7], 6420 past the backend-shaped allocation, 55/64 canary words smashed. Patched twin (fix.diff clamp) shows zero corruption.
No comments yet.