fiji clock-stretcher walk overflows Sclk_voltageOffset[8] using the raw VBIOS SCLK-dependency count
Summary
DF-1272 sibling: the walk uses the RAW VBIOS count (<=255), not even the dedup'd dpm count - writing Sclk_voltageOffset[8] (the DpmTable tail): counts past ~24 run off smc_state_table into the rest of the fiji_smumgr alloc and past it. The walk executes BEFORE the stretch_amount validation, so a 'rejected' VBIOS still smears first. Clamp fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4004 Β· 8 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.8 KB | β raw | |
| VERDICT.md | β | 1.5 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-4004 β fiji clock-stretcher walk overflows Sclk_voltageOffset[8] with the raw VBIOS SCLK-dep count
File: sys/dev/drm/amd/powerplay/smumgr/fiji_smumgr.c:1706-1719 (DDT read walk :1792-1810)
Class: kernel heap OOB write (memcorrupt) β DF-1272 (tonga Sclk_voltageOffset[8]) sibling
Severity: Medium Β· Confidence: certain (source) Β· runtime hardware-gated
Build / Run / Expected
Same demonstrator as DF-4001 (./build.sh && ./run.sh, section === DF-4004 ===):
dep_sclk->count=12 (RAW count, not the dedup'd dpm count): writes at [8..11] are OOB array sits at DpmTable+1576 of 1632B ... count 255 writes 247B past the array, off the end of smc_state_table
Source chain
fiji_populate_clock_stretcher_data_table walks
for (i = 0; i < sclk_table->count; i++) where sclk_table = table_info->vdd_dep_on_sclk
(the RAW VBIOS dep table, count = ucNumEntries β€ 255 β not even the dedup'd
dpm count) and writes smc_state_table.Sclk_voltageOffset[i] (:1718) β a fixed
uint8_t[8] at DpmTable+1576 (smu73_discrete.h:361) followed only by
ClockStretcherDataTable/CKS_LOOKUPTable (struct tail): count > ~24 runs past the
whole smc_state_table into the remainder of the fiji_smumgr allocation
(ulv_setting/power_tune_table) and beyond. The second walk (:1792) reads
GraphicsLevel[j] for j < GraphicsDpmLevelCount (also unclamped, OOB read).
Gating: PHM_PlatformCaps_ClockStretcher is set for PP_TABLE_V1 parts when
feature_mask & PP_CLOCK_STRETCH_MASK && usClockStretchAmount != 0
(smu7_hwmgr.c:1664-1668); the walk executes BEFORE the stretch_amount range
check at :1731, so even a "rejected" VBIOS amount smears the table first.
Fix
fix.diff (shared): clamp both walks (i < 8 / j < SMU73_MAX_LEVELS_GRAPHICS).
Compile-validated via nativekernel rebuild (fix_build.log).
VERDICT β DF-4004
Status: inconclusive at runtime (hardware-gated); source-certain.
Demonstrated (run.log, section DF-4004): with raw vdd_dep_on_sclk->count = 12
the walk at fiji_smumgr.c:1706-1719 writes Sclk_voltageOffset[8..11] β the
array is uint8_t[8] at DpmTable+1576 of 1632 (smu73_discrete.h:361), the
struct tail. Count 255 writes 247 B past the array, off the end of smc_state_table
into the remainder of the fiji_smumgr allocation and past it. Distinct from
DF-4001: this walk uses the RAW dependency-table count (table_info->vdd_dep_on_sclk),
not the dedup'd dpm count, so even a VBIOS whose dedup collapses below 8 still
overflows. The DDT walk :1792-1795 additionally OOB-reads GraphicsLevel[j].
Gating (PP_TABLE_V1 + feature_mask + usClockStretchAmount != 0,
smu7_hwmgr.c:1664-1668) is satisfiable by the crafted vBIOS itself, and the
walk precedes the stretch_amount range check at :1731.
DF-1272 (tonga Sclk_voltageOffset[8]) sibling; Medium because of the cap gate and the 1-byte-per-entry write granularity. Hardware-gated (env.txt).
Fix: fix.diff clamps both walks; 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-4004/fix.diff; findings/poc/DF-4001/fix_build.log; findings/poc/DF-4007/run.log (PATCHED model run for DF-4007)
Confirmed kernel references
- sys/dev/drm/amd/powerplay/smumgr/fiji_smumgr.c:1706
- sys/dev/drm/amd/powerplay/smumgr/fiji_smumgr.c:1718
- sys/dev/drm/amd/powerplay/smumgr/fiji_smumgr.c:1731
- sys/dev/drm/amd/powerplay/smumgr/fiji_smumgr.c:1792
- sys/dev/drm/amd/powerplay/inc/smu73_discrete.h:361
- sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c:1664
Detail
Exploit chain
crafted vBIOS with ClockStretchAmount!=0 -> populate_clock_stretcher_data_table with dep count>8 -> OOB byte writes off the end of smc_state_table
Evidence (decisive lines)
run.log (DF-4004 section: writes at [8..11] OOB, array at DpmTable+1576 of 1632, 247B past at count 255); 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
Clamp the clock-stretcher walks to 8 / SMU73_MAX_LEVELS_GRAPHICS (fix.diff)
Verdict
Source-certain heap OOB write: fiji_populate_clock_stretcher_data_table walks i < table_info->vdd_dep_on_sclk->count (RAW VBIOS count, <=255) writing Sclk_voltageOffset[8] (fiji_smumgr.c:1706-1718) and reads GraphicsLevel[j] for j<GraphicsDpmLevelCount (:1792-1795); array is the DpmTable tail (+1576 of 1632), so counts past ~24 run off smc_state_table into the fiji_smumgr allocation and beyond. Walk precedes the stretch_amount validation (:1731), so a 'rejected' VBIOS still smears first. DF-1272 (tonga) sibling. Hardware-gated: inconclusive at runtime, source-certain.
No comments yet.