β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-4000

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)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4000 Β· 12 files
FileTypeDescriptionSize
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.

VERDICT.md
↓ download raw

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 β€” writes smc_state_table.GraphicsLevel[i] for i < dpm_table->sclk_table.count (iceland_smumgr.c:980-990); array is GraphicsLevel[SMU71_MAX_LEVELS_GRAPHICS=8] (smu71_discrete.h:270). Also the [count-1] store at :997 and the pcieDpmLevel loop at :1026-1028.
  • iceland_populate_all_memory_levels β€” writes MemoryLevel[i] for i < mclk_table.count (:1361-1369) plus MemoryLevel[count-1] (:1385); array is MemoryLevel[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 object SMU71_Discrete_MCArbDramTimingTable arb_regs (:1616) with entries[8][4] (:179 smu71_discrete.h) indexed [i][j] for i < 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 β€” writes mc_regs->data[i] for i < mclk_table.count (:1761-1766); data[SMU71_DISCRETE_MC_REGISTER_ARRAY_SET_COUNT=4] (smu71_discrete.h:370), and iceland_update_and_upload_mc_reg_table copies sizeof(MCRegisterSet)*count bytes from mc_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_image checks image_size & 3 (:195) and > ICELAND_SMC_SIZE (:200); iceland_upload_smc_firmware_data checks limit >= 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 == 0 rejected at :513 before the entries[i-1] fallback at :525 β€” safe. (iceland_populate_mvdd_value (:1395-1419) does cross-index mvdd_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_table sources with SMU71 structures β€” no V1/SMU-mismatch path reaches this file. iceland_get_mac_definition returns the SMU71 limits consistently.
  • Killed candidates: iceland_populate_smc_link_level i <= count off-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_registers j-bounds asserted before every write (:2516,2532,2549); iceland_copy_vbios_smc_reg_table asserts 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_sidd assert 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

fixed
baseline no→ patch + rebuild →patched clean

fixed (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
↓ fix.diffDragonFly dfbsd 6.5-DEVELOPMENT (nativekernel X86_64_GENERIC, patched, completed 11:59:41, error_count=0)

Confirmed kernel references

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).