fiji_get_dependency_volt_by_clk fall-through reads dep_table->entries[count] twice (one-entry heap OOB read)
Summary
When the requested clock exceeds every entry, the loop falls through with i==count and the tail block reads entries[i].vddc and entries[i].mvdd - one entry past the exact-size kmalloc. Sibling reads correctly use entries[i-1]. Hot path; upstream-4.x-carried; value used only as a branch condition - Low. entries[i-1] fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4005 Β· 8 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.5 KB | β raw | |
| VERDICT.md | β | 1.4 KB | β raw | |
| build.sh | β | 65 B | view raw | |
| run.sh | β | 89 B | view raw | |
| run.log | β | 3.8 KB | view raw | |
| env.txt | β | 493 B | view raw | |
| fix.diff | β | 7.7 KB | view raw | |
| trigger_analysis.c | β | 17.3 KB | view raw |
DF-4005 β fiji_get_dependency_volt_by_clk fall-through reads dep_table->entries[count] (one-entry heap OOB read Γ2)
File: sys/dev/drm/amd/powerplay/smumgr/fiji_smumgr.c:404-414 (reads at :406 and :413)
Class: kernel heap OOB read (kernleak-class; value used only as a branch condition)
Severity: Low Β· Confidence: certain (source) Β· runtime hardware-gated
Build / Run / Expected
Same demonstrator as DF-4001 (./build.sh && ./run.sh, section === DF-4005 ===):
count=3, i=3 after fall-through; entries[i].mvdd reads bytes at +60, 12 bytes past the 3-entry heap object value read = 0x0001 (poisoned adjacent-slab byte) β kernel heap adjacent-slab bytes consumed as a branch condition
Source chain
When the requested clock exceeds every entry (loop :368-396 falls through),
i == dep_table->count and the tail block reads
- :406 dep_table->entries[i].vddc (inside the vddci lookup),
- :413 dep_table->entries[i].mvdd (mvdd condition),
both one entry past the kmalloc(count * sizeof(entry)) allocation made in
process_pptables_v1_0.c:425-436/378-391. The in-bounds twin reads correctly use
entries[i - 1] (:399, :404, :414). The OOB bytes only select whether
*mvdd gets set β no direct disclosure, but a genuine heap OOB read on the hot
per-level voltage path. Carried from the upstream 4.x code as-is.
Fix
fix.diff (shared): use entries[i - 1] at both sites. Compile-validated via
nativekernel rebuild (fix_build.log).
VERDICT β DF-4005
Status: inconclusive at runtime (hardware-gated); source-certain.
Demonstrated (run.log, section DF-4005): the fall-through tail of
fiji_get_dependency_volt_by_clk (fiji_smumgr.c:398-416) executes with
i == dep_table->count when the requested clock exceeds every entry; it reads
dep_table->entries[i].vddc at :406 and dep_table->entries[i].mvdd at :413
β one entry (12 B of a 16 B record) past the exact-size heap allocation made by
process_pptables_v1_0.c:425-436/378-391. The demonstrator's poisoned redzone
byte (0x0001) shows adjacent-slab content being consumed as the branch condition
that decides whether *mvdd is populated. All sibling reads in the same block
correctly use entries[i - 1] (:399/:404/:414) β an off-by-one carried from
the 4.x upstream code. Impact is a bounded kernel heap OOB read with no direct
disclosure channel β Low.
Called on every graphics/memory level population (:957, :1181) β hot path,
not error path. Hardware-gated (env.txt).
Fix: fix.diff uses entries[i - 1] at both sites; nativekernel rebuild OK
(fix_build.log), reverted.
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
fixedfixed (compile-validated): both diffs applied to clean guest /usr/src (fiji_smumgr.c md5 800babd0..->d50bdc81.., i915_gem_execbuffer.c 334c7bd9..->dc882976..), make nativekernel KERNCONF=X86_64_GENERIC completed with error_count=0 under -Werror (fix_build.log); behavior additionally model-verified for DF-4007 (PATCHED run balanced). Runtime re-test impossible on this guest (no AMD/Intel GPU). Patch reverted after validation.
findings/poc/DF-4005/fix.diff; findings/poc/DF-4001/fix_build.log; findings/poc/DF-4007/run.log (PATCHED model run for DF-4007)
Confirmed kernel references
Detail
Exploit chain
crafted vBIOS -> any graphics/memory level population -> get_dependency_volt_by_clk fall-through -> 2x one-entry heap OOB reads consumed as branch conditions
Evidence (decisive lines)
run.log (DF-4005 section: entries[count].mvdd read 12B past the exact-size allocation, poisoned redzone byte consumed as branch condition); VERDICT.md; fix_build.log; env.txt
PoC changes
Pass-2 reviewer authored demonstrator compiling the kernel's own smu73.h/smu73_discrete.h (packed) so sizeof/offsets are the kernel's; fix.diff generated mechanically against the pristine file and compile-validated via full nativekernel rebuild on the guest (shared build with DF-4001..DF-4007).
Verified recommended fix
Use dep_table->entries[i - 1] at fiji_smumgr.c:406 and :413 (fix.diff)
Verdict
Source-certain one-entry heap OOB reads (x2) in the fall-through tail of fiji_get_dependency_volt_by_clk (fiji_smumgr.c:406 entries[i].vddc, :413 entries[i].mvdd with i==dep_table->count after the loop): both read one 16-byte record slot (12 bytes in) past the exact-size kmalloc made by process_pptables_v1_0.c:425-436. Demonstrator shows adjacent-slab bytes (poisoned 0x0001) consumed as the condition deciding whether *mvdd is set. Sibling reads correctly use entries[i-1]; upstream-4.x-carried off-by-one. Hot path (every level population). Bounded read, no direct disclosure -> Low. Hardware-gated: inconclusive at runtime, source-certain.
No comments yet.