vegam_get_dependency_volt_by_clk reads dep_table->entries[count] one record past the heap allocation in the clock-above-max path
Summary
When the requested clock exceeds every dependency entry, the loop exits with i==count; the tail path uses entries[i-1] correctly but the MVDD predicate at :661 reads entries[i].mvdd - exactly one record past the kzalloc'd count-record table. 2-byte OOB heap read used as a boolean; wrong-MVDD selection at worst; hit on every above-max clock query. One-token entries[i-1] fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4072 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| verdict.json | β | 2.0 KB | view raw | |
| README.md | β | 258 B | β raw | |
| VERDICT.md | β | 1.5 KB | β raw | |
| fix.diff | β | 299 B | view raw | |
| manifest.json | β | 773 B | view raw |
DF-4072 β vegam_get_dependency_volt_by_clk entries[count] one-past-end heap OOB read (pass 2)
File: sys/dev/drm/amd/powerplay/smumgr/vegam_smumgr.c:661 Source-level finding. No executable PoC (hardware-gated); see VERDICT.md for the line-by-line trace.
DF-4072 VERDICT β source-level certain, hardware-gated
Root cause
- vegam_get_dependency_volt_by_clk() searches
for (i = 0; i < dep_table->count; i++)for the first entry with clk >= clock (vegam_smumgr.c:614-642). When the clock exceeds every entry, the loop exits with i == dep_table->count. - The tail path then uses entries[i-1] correctly at :645/:653, but the MVDD predicate at :661 reads
dep_table->entries[i].mvddβ i == count β exactly ONE RECORD past the allocation. - Allocation: process_pptables_v1_0.c:381-389 (mclk) and :425-470 (sclk) kzalloc exactly
sizeof(count field) + count * sizeof(record)β entries[count] is genuinely past the heap object.
Impact
2-byte OOB heap read used as a boolean; if it happens to be nonzero the code then programs entries[i-1].mvdd (in-bounds). Worst realistic effect: wrong MVDD selection + an OOB read that can fault at a slab boundary. Hit on every "clock above table max" query (e.g. ACPI level with boot clock above the dependency table's max β vegam_populate_smc_acpi_level:1125/1163).
Fix
dep_table->entries[i].mvdd -> dep_table->entries[i - 1].mvdd at :661.
Sibling pattern of the fiji/polaris off-by-ones filed in pass 2 (DF-40xx series).
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)
vegam_smumgr.c:614-642 loop, :645 entries[i-1] (correct), :661 entries[i] with i==count (OOB read)
PoC changes
n/a (source-level)
Verified recommended fix
Use dep_table->entries[i - 1].mvdd at line 661.
Verdict
Source-level certain, hardware-gated. In vegam_get_dependency_volt_by_clk(), when the requested clock exceeds every table entry the for-loop exits with i == dep_table->count, and line 661 reads dep_table->entries[i].mvdd -- exactly one record past the kzalloc'd 'count'-record table (process_pptables_v1_0.c allocates sizeof + count*sizeof(record) exactly). One-record heap OOB read (2-byte mvdd field) whose value is only used as a boolean; the value actually programmed comes from entries[i-1]. Sibling of the polaris/fiji off-by-ones; hit on every above-max clock query (ACPI level with boot sclk above table max, etc.).
No comments yet.