Unclamped VBIOS SCLK/MCLK DPM counts overflow the iceland SMC state tables and the 384-byte stack MC-arb table: GraphicsLevel[8], MemoryLevel[4], arb_regs.entries[8][4] (kernel STACK), mc_regs.data[4] β DF-3908/3909/3939/3940 family with iceland's tighter mclk bound (count 5 suffices)
Summary
Every iceland SMC-table populate walk uses the raw VBIOS dependency-table counts (u8, unclamped through smu7_setup_dpm_tables_v0): GraphicsLevel[8] for i<sclk count incl. unguarded [count-1] and the pcieDpmLevel loop; MemoryLevel[4] incl. unguarded [count-1]; STACK SMU71_Discrete_MCArbDramTimingTable entries[8][4] indexed [i][j] (mclk count 5 already writes past the 384-byte stack object); mc_regs.data[4] plus a sizeof*count copy off the end. Overwrites land inside the kzalloc'd iceland_smumgr and past the whole allocation, and up to +216 bytes past the stack frame. Crafted-vBIOS physical attacker on Topaz-class; deterministic, source-certain. Guest demonstrator with verbatim struct replicas (4/12 GraphicsLevel writes +192B, 2/6 MemoryLevel +144B, 26/72 stack writes max entry 49 of 32 +216B); full patched nativekernel build -Werror clean. Hardware-gated.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4000 Β· 12 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.4 KB | β raw | |
| VERDICT.md | β | 6.7 KB | β raw | |
| trigger_analysis.c | β | 7.4 KB | view raw | |
| build.sh | β | 107 B | view raw | |
| run.sh | β | 98 B | view raw | |
| build.log | β | 11 B | view raw | |
| run.log | β | 1.4 KB | view raw | |
| env.txt | β | 162 B | view raw | |
| fix.diff | β | 4.5 KB | view raw | |
| fix_build.log | β | 4.2 KB | view raw | |
| fix_kernel_full.log | β | 5.1 MB | β download | |
| verdict.json | β | 4.7 KB | view raw |
DF-4000 β Unclamped VBIOS SCLK/MCLK DPM counts overflow iceland SMC tables (GraphicsLevel[8], MemoryLevel[4], 384-B stack arb table, mc_regs.data[4])
File: sys/dev/drm/amd/powerplay/smumgr/iceland_smumgr.c (pass 2)
Class: kernel heap + stack OOB writes from crafted VBIOS (hardware-gated).
Sibling of DF-3908/DF-3909 (tonga) and DF-3939/DF-3940 (CI); DF-1166 covers the
upstream smu7_hwmgr dpm_levels[8] overflow on the same chain.
Reproduce (index-math demonstrator; kernel fault needs a Topaz GPU with crafted VBIOS)
scp -F dfbsd-qemu/config trigger_analysis.c dfbsd-maxx:/tmp/ vm.sh run_user 'cc -O2 -Wall -o /tmp/iceland_trig /tmp/trigger_analysis.c && /tmp/iceland_trig'
Expected
GraphicsLevel[8]: +48 bytes past the GraphicsLevel[8] array -> 4/12 writes OOB (max +192) MemoryLevel[4]: +72 bytes past -> 2/6 writes OOB (max +144), [count-1] indexes [5] arb_regs.entries[7][4]: linear entry 32 of 32 -> 26 of 72 STACK writes OOB (max +216 past the 384-byte object) 2/6 mc_regs.data[] writes OOB + copy_bytes of sizeof(MCRegisterSet)*6 past mc_regs DONE (source-certain; kernel fault itself hardware-gated)
Fix validation
fix.diff applied to clean guest /usr/src; full make nativekernel KERNCONF=X86_64_GENERIC:
completed 11:59:41, error_count=0, iceland_smumgr.c compiled under -Werror
(fix_build.log / fix_kernel_full.log:11214). Patch reverted after validation.
DF-4000 β VERDICT
Finding: The iceland (Topaz) SMU manager feeds the raw VBIOS PowerPlay
SCLK/MCLK dependency-table counts (u8 ucNumEntries, never clamped) into
every SMC-table populate walk, indexing arrays dimensioned 8/4 β the
DF-3909/DF-3940 family on iceland's tighter bounds, including a
kernel-stack OOB write:
iceland_populate_all_graphic_levelsβ writessmc_state_table.GraphicsLevel[i]fori < dpm_table->sclk_table.count(iceland_smumgr.c:980-990); array isGraphicsLevel[SMU71_MAX_LEVELS_GRAPHICS=8](smu71_discrete.h:270). Also the[count-1]store at :997 and thepcieDpmLevelloop at :1026-1028.iceland_populate_all_memory_levelsβ writesMemoryLevel[i]fori < mclk_table.count(:1361-1369) plusMemoryLevel[count-1](:1385); array isMemoryLevel[SMU71_MAX_LEVELS_MEMORY=4](smu71_discrete.h:272) β count 5 already overflows (CI needed 7 against its 6).iceland_program_memory_timing_parametersβ stack objectSMU71_Discrete_MCArbDramTimingTable arb_regs(:1616) withentries[8][4](:179 smu71_discrete.h) indexed[i][j]fori < sclk_count,j < mclk_count(:1621-1632) β the DF-3908/DF-3939 twin; mclk count 5 suffices for iceland (CI needed 7).iceland_convert_mc_reg_table_to_smcβ writesmc_regs->data[i]fori < mclk_table.count(:1761-1766);data[SMU71_DISCRETE_MC_REGISTER_ARRAY_SET_COUNT=4](smu71_discrete.h:370), andiceland_update_and_upload_mc_reg_tablecopiessizeof(MCRegisterSet)*countbytes frommc_regs.data[0](:1796-1799) β OOB read of the softc into SMC SRAM.
Provenance of the counts (all three hops verified in-tree):
ATOM_PPLIB dep table ucNumEntries (u8) β
get_clock_voltage_dependency_table processpptables.c:375-401 (kzalloc of
exactly count entries, no upper bound) β hwmgr->dyn_state.vddc_dependency_on_{s,m}clk
β smu7_setup_dpm_tables_v0 smu7_hwmgr.c:689-697/704-711 (copies every
entry, incrementing dpm_table.{s,m}clk_table.count with no clamp β and
itself writes past dpm_levels[MAX_REGULAR_DPM_NUMBER=8], smu7_hwmgr.h:100,
already filed as DF-1166) β the iceland loops above. Topaz is pinned to
this path: hwmgr.c:114-122 (CHIP_TOPAZ β iceland_smu_funcs,
PP_TABLE_V0). Voltages and PCIE are trimmed upstream
(smu7_construct_voltage_tables smu7_hwmgr.c:323-349; pcie table count
capped β€ 7 with the boot-level reservation smu7_hwmgr.c:560-605) β the
clock DPM counts are the untrimmed family.
Status: inconclusive (hardware-gated) β source-certain. The guest
demonstrator reproduces the exact index math with verbatim struct replicas
(sizeof GraphicsLevel=48, MemoryLevel=72, MCArbDramTimingTable=384): for a
crafted VBIOS with sclk=12/mclk=6 dep entries β 4/12 GraphicsLevel writes
(+192 B past the array), 2/6 MemoryLevel writes (+144 B past, walking
LinkLevel/ACPILevel/β¦ inside the kzalloc'd iceland_smumgr), 26 of 72
stack arb_regs writes OOB (max linear entry 49 of 32, +216 B past the
384-byte stack object), 2/6 mc_regs.data writes OOB. The in-kernel fault
could not be observed: the QEMU guest has no AMD GPU (env.txt: amd-gpu=0)
and the trigger requires a Topaz card whose VBIOS carries the crafted
PowerPlay tables β matching the DF-3908/3939/3940 precedent for this
family (physical-attacker / malicious-VBIOS threat model; also reachable
via a corrupted vbios image flashed or supplied to the driver).
Why each checklist item is or is not a finding
- (a) SMC table populate walks β this finding.
- (b) firmware header parses:
iceland_smu_upload_firmware_imagechecksimage_size & 3(:195) and> ICELAND_SMC_SIZE(:200);iceland_upload_smc_firmware_datacheckslimit >= byte_count(:163); firmware comes from root-controlled /lib/firmware β no defect. - (c) AVFS dep-table walks: no AVFS code exists in iceland_smumgr.c (grep -i avfs β no matches; Topaz AVFS is handled in smu7_hwmgr) β n/a.
- (d)
iceland_get_dependency_volt_by_clk(:506-528):count == 0rejected at :513 before theentries[i-1]fallback at :525 β safe. (iceland_populate_mvdd_value(:1395-1419) does cross-indexmvdd_voltage_table.entries[i]by the dependency-table count, which can exceed the trimmed 4-entry voltage table β but its only caller passes mclk=0 (:1504), which always matches at i=0; unreachable as written, noted as latent.) - (e) data table version gating: Topaz is pinned to PP_TABLE_V0
(hwmgr.c:114-122) and every iceland populate function consistently
consumes V0
dyn_state/dpm_tablesources with SMU71 structures β no V1/SMU-mismatch path reaches this file.iceland_get_mac_definitionreturns the SMU71 limits consistently. - Killed candidates:
iceland_populate_smc_link_leveli <= countoff-by-one (:772) β pcie count β€ 7 by construction (boot-level reservation, smu7_hwmgr.c:560-569) so max index 7 < LinkLevel[8] β safe; BAPMTI default walk (:1893-1902) β 5Γ3Γ1 = 15 == bapmti_r[15] exact fit;iceland_set_mc_special_registersj-bounds asserted before every write (:2516,2532,2549);iceland_copy_vbios_smc_reg_tableasserts last β€ 16 / num_entries β€ MAX_AC_TIMING_ENTRIES (:2484-2487); fan-table div0 = DF-1323 and mvdd loop bound = DF-1324 (knowns, not re-reported);iceland_populate_vddc_vid/bapm_vddc_vid_siddassert counts β€ 8 (:398-399, :422); voltage-level arrays bounded by the upstream trims (smu7_hwmgr.c:323-349) to SMU71 limits 8/4/4.
Fix
fix.diff (8 hunks, applies clean to pristine /usr/src β md5 verified):
clamp every walk to its array bound β sclk_count =
min(count, SMU71_MAX_LEVELS_GRAPHICS), mclk_count =
min(count, SMU71_MAX_LEVELS_MEMORY) used for the loops, the [count-1]
stores and the reported *DpmLevelCount; && guards in the arb-timing
and mc_reg loops; upload size clamped to
SMU71_DISCRETE_MC_REGISTER_ARRAY_SET_COUNT. The structural fix belongs
upstream in smu7_setup_dpm_tables_v0 (DF-1166's domain: clamp counts
before they enter dpm_table / dpm_levels[8]).
Fix validation: applied to the guest's clean /usr/src
(patch-OK, md5 e3bce6β¦β1f1e44β¦), full make nativekernel KERNCONF=X86_64_GENERIC
rebuild: started 11:31:31, completed 11:59:41, error_count=0 with the
patched iceland_smumgr.c compiled under -Werror at fix_kernel_full.log:11214
(fix_build.log summary). Runtime re-test impossible on this guest (no AMD
GPU). Patch reverted after validation (md5 back to pristine).
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): fix.diff applied to clean guest /usr/src (md5 e3bce6..->1f1e44.., patch-OK); make nativekernel KERNCONF=X86_64_GENERIC completed with error_count=0 and the patched iceland_smumgr.c compiled under -Werror (fix_kernel_full.log:11214). Runtime re-test impossible on this guest (no AMD GPU). Patch reverted after validation (md5 restored).
findings/poc/DF-4000/fix_build.log; findings/poc/DF-4000/fix_kernel_full.log; findings/poc/DF-4000/fix.diff
Confirmed kernel references
- sys/dev/drm/amd/powerplay/smumgr/iceland_smumgr.c:980
- sys/dev/drm/amd/powerplay/smumgr/iceland_smumgr.c:997
- sys/dev/drm/amd/powerplay/smumgr/iceland_smumgr.c:1026
- sys/dev/drm/amd/powerplay/smumgr/iceland_smumgr.c:1361
- sys/dev/drm/amd/powerplay/smumgr/iceland_smumgr.c:1385
- sys/dev/drm/amd/powerplay/smumgr/iceland_smumgr.c:1616
- sys/dev/drm/amd/powerplay/smumgr/iceland_smumgr.c:1621
- sys/dev/drm/amd/powerplay/smumgr/iceland_smumgr.c:1761
- sys/dev/drm/amd/powerplay/smumgr/iceland_smumgr.c:1796
- sys/dev/drm/amd/powerplay/inc/smu71.h:32
- sys/dev/drm/amd/powerplay/inc/smu71_discrete.h:179
- sys/dev/drm/amd/powerplay/inc/smu71_discrete.h:270
- sys/dev/drm/amd/powerplay/inc/smu71_discrete.h:370
- sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c:689
- sys/dev/drm/amd/powerplay/hwmgr/processpptables.c:391
- sys/dev/drm/amd/powerplay/hwmgr/hwmgr.c:114
Detail
Evidence (decisive lines)
run.log (demonstrator output on guest: 26/72 stack writes OOB, max linear entry 49 of 32, +216B past the 384-byte stack object; heap arrays +192B/+144B); VERDICT.md full three-hop provenance + killed-candidates list; fix_build.log (patch-OK + started/completed + error_count=0); fix_kernel_full.log:11214 (iceland_smumgr.c compile line, -Werror); env.txt (amd-gpu=0)
PoC changes
Pass-2 reviewer authored demonstrator (verbatim struct replicas from smu71_discrete.h so sizeof/offsets are the kernel's own) + fix.diff generated mechanically against the pristine file (8 hunks); fix compile-validated via full nativekernel rebuild on the guest.
Verified recommended fix
Clamp all iceland populate walks to SMU71_MAX_LEVELS_GRAPHICS/SMU71_MAX_LEVELS_MEMORY (and MC_REGISTER_ARRAY_SET_COUNT) as in fix.diff; structurally, clamp the counts in smu7_setup_dpm_tables_v0 (DF-1166)
Verdict
Source-certain kernel heap + stack OOB writes: the iceland (Topaz) SMC-table populate walks index GraphicsLevel[8], MemoryLevel[4], the 384-byte STACK MCArbDramTimingTable (entries[8][4]) and mc_regs.data[4] with the raw VBIOS SCLK/MCLK dependency-table counts (u8 ucNumEntries, unclamped through processpptables.c:391 -> smu7_hwmgr.c:689-711 -> dpm_table, Topaz pinned to this path at hwmgr.c:114-122). Iceland's bounds are tighter than the CI/tonga siblings: mclk count 5 (vs 7 for CI) already smashes MemoryLevel[4] and the stack arb table. Guest demonstrator with verbatim struct replicas reproduces the exact index math (sclk=12/mclk=6: 4/12 GraphicsLevel writes +192B, 2/6 MemoryLevel writes +144B, 26/72 stack writes +216B past the 384B object, 2/6 mc_regs.data writes); the in-kernel fault could not be observed - no AMD GPU in QEMU and the trigger requires a Topaz card with a crafted VBIOS (physical attacker / malicious vBIOS). Hardware-gated, matching the DF-3908/3939/3940 precedent. Fix compile-validated by full nativekernel rebuild (error_count=0, iceland_smumgr.c under -Werror).
No comments yet.