Kernel stack OOB write in tonga_program_memory_timing_parameters: VBIOS-controlled SCLK/MCLK DPM counts index fixed stack table arb_regs.entries[8][4]
Summary
The function declares the 384-byte ARB timing table on the stack (entries[8][4]) and indexes it with i < sclk_table.count, j < mclk_table.count - counts copied straight from the VBIOS dependency tables (u8, never clamped). A crafted VBIOS with >8 distinct SCLK or >4 MCLK levels makes the loops write up to ~15.3KB past a 384-byte kernel stack frame with VBIOS-derived GPU DRAM-timing dwords - return-address smash potential on a kernel built -fno-stack-protector. Reached at DPM enable and on OD updates. VERIFIED: guest demonstrator shows 26 OOB writes up to +216B past the frame for a modest 12x6 table, scaling to ~15KB for u8-max counts. Crafted-VBIOS attacker gets a kernel-stack write primitive with semi-controlled content.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3908 Β· 11 files| File | Type | Description | Size | |
|---|---|---|---|---|
| trigger_analysis.c | trigger-source | userspace demonstrator of the kernel index/pointer/division arithmetic | 2.7 KB | view raw |
| build.sh | build-script | cc build of the demonstrator | 65 B | view raw |
| run.sh | run-script | runs the demonstrator | 89 B | view raw |
| build.log | build-log | guest compiler output | 11 B | view raw |
| run.log | run-log | guest runtime output (decisive run) | 319 B | view raw |
| env.txt | environment | guest uname + pciconf (no AMD GPU / no MPT HBA) | 838 B | view raw |
| fix.diff | suggested-fix | git-apply-able unified diff | 926 B | view raw |
| fix_build.log | build-log | fix apply + nativekernel rebuild summary, rc=0 -Werror | 6.3 KB | view raw |
| VERDICT.md | verdict | full verification narrative | 3.0 KB | β raw |
| README.md | readme | human-readable summary | 2.4 KB | β raw |
| fix_kernel_full.log | build-log | full 33k-line nativekernel build log (all five fixes applied) | 5.6 MB | β download |
DF-3908 β Tonga/Fiji SMC ARB timing table: kernel stack OOB write via unclamped VBIOS DPM counts
File: sys/dev/drm/amd/powerplay/smumgr/tonga_smumgr.c
Lines: 1492-1507 (tonga_program_memory_timing_parameters)
Severity: High (kernel stack corruption) β hardware-gated (Tonga/Fiji GPU + crafted VBIOS)
Class: memcorrupt / CWE-787 (out-of-bounds write), pass 2 (checklist item (a): clock-count-driven stack tables)
Build
./build.sh # cc -O2 -Wall -o trigger_analysis trigger_analysis.c (on the DragonFly guest)
Run
./run.sh
Expected output
arb_regs stack object : 384 bytes (entries[8][4], 12B each) VBIOS dep counts (sclk,mclk) : 12 x 6 total writes : 72 OOB writes past stack object : 26 (first at +384, worst at +588..+599) => kernel stack corruption up to 216 bytes past a 384-byte frame trigger rc=1 (1 == OOB writes demonstrated)
The harness reproduces the exact index arithmetic of the kernel loops; the kernel path itself requires Tonga/Fiji hardware (absent from the QEMU guest β see env.txt), hence the PoC verdict is inconclusive (source-certain, hardware-gated), consistent with DF-1271/DF-1272/DF-1280 precedent.
Root cause
data->dpm_table.sclk_table.count / mclk_table.count are filled by
smu7_setup_dpm_tables_v1() (smu7_hwmgr.c:752-830) directly from the VBIOS
SCLK/MCLK dependency-table entry counts (u8, β€255, deduplicated only β the
dpm_levels[8] overflow there is DF-1166). No code path clamps them to the
SMU72 table sizes before tonga_program_memory_timing_parameters() indexes
the stack object SMU72_Discrete_MCArbDramTimingTable arb_regs
(entries[SMU__NUM_SCLK_DPM_STATE=8][SMU__NUM_MCLK_DPM_LEVELS=4], 12
bytes/entry = 384 bytes) with
for (i...) for (j...) populate(..., &arb_regs.entries[i][j]).
With a crafted VBIOS reporting >8 SCLK or >4 MCLK distinct levels, writes run
up to ~15 KB past the stack frame with GPU DRAM-timing values derived from
VBIOS-controlled clocks (return-address smash potential on machines without
stack protector β the kernel is built -fno-stack-protector).
Fix
fix.diff clamps both loop bounds with MIN(count, SMU72_MAX_LEVELS_*).
Validated: applied to the guest's clean /usr/src, full
make nativekernel KERNCONF=X86_64_GENERIC rebuild β rc=0, -Werror clean
(fix_build.log, fix_kernel_full.log line 28191 compiles tonga_smumgr.c).
DF-3908 β Verification Verdict
Status: inconclusive (reproduced=0) Impact: none (no Tonga/Fiji hardware on the guest) Confidence: certain (source-level)
Finding
VBIOS-controlled SCLK/MCLK DPM counts (bounded only by the u8 dependency-table
entry count) index the fixed entries[8][4] stack table
SMU72_Discrete_MCArbDramTimingTable arb_regs in
tonga_program_memory_timing_parameters() without any clamp β kernel stack
OOB write at driver init / OD reprogram time.
Source proof chain
process_pptables_v1_0.cget_sclk_voltage_dependency_table/get_mclk_voltage_dependency_tableallocate the dep tables withcount = ucNumEntries(u8 β€ 255) β count is VBIOS-controlled.smu7_hwmgr.c:752-830smu7_setup_dpm_tables_v1()copies every distinct clock intodpm_table->sclk_table/mclk_table, incrementingcountper accepted entry β never clamped to SMU72_MAX_LEVELS_* (the dpm_levels[8] overflow on the way is already filed as DF-1166).smu7_hwmgr.c:3780-3817smu7_trim_*only flipsenabled, never reduces count.tonga_smumgr.c:2296callstonga_program_memory_timing_parameters()fromtonga_init_smc_table()(and from the OD path at :2552-2561).tonga_smumgr.c:1492declaresarb_regs(384-byte stack object);:1497-1502indexesarb_regs.entries[i][j]fori < sclk_table.count,j < mclk_table.countβ OOB for iβ₯8 / jβ₯4. Max extent: (2554+255)12 β 15.3 KB past a 384-byte frame.- Array dims:
smu72_discrete.h:156-169(entries[SMU__NUM_SCLK_DPM_STATE=8][SMU__NUM_MCLK_DPM_LEVELS=4], entry = 2Γuint32 + uint8 + pad = 12 B).
Why inconclusive, not reproduced
The path executes only during AMD GPU powerplay init on Tonga/Fiji
(chip family AMDGPU_FAMILY_VI, tonga/fiji ASICs). The QEMU guest has no AMD
GPU (env.txt: pciconf shows only Intel/QEMU virtual PCI devices). The
userspace demonstrator (run.log) reproduces the exact index arithmetic and
shows 26 OOB writes for a modest 12Γ6 crafted VBIOS, but cannot fault a
kernel stack that never runs.
Fix validation
fix.diff clamps both loops with MIN(count, SMU72_MAX_LEVELS_*). Applied
on the guest's clean /usr/src together with DF-3909/3910/3911/3912; full
make -j4 nativekernel KERNCONF=X86_64_GENERIC:
tonga_smumgr.c compiled with -Werror (fix_kernel_full.log:28191),
error count 0, "Kernel build for X86_64_GENERIC completed", rc=0
(fix_build.log). fix_status = fixed (compile-validated; runtime
validation requires hardware).
Prior art
Checklist item (a) β the smu7_hwmgr.c twin (amd_pp_clocks.clock[16] stack copies) is DF-3684; this is the tonga_smumgr.c stack-table sink, not covered by DF-1271..DF-1275.
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; make -j4 nativekernel KERNCONF=X86_64_GENERIC completed rc=0 with 0 errors; tonga_smumgr.c compiled with -Werror (fix_kernel_full.log:28191). Runtime re-test impossible on this guest (no AMD GPU).
fix_build.log (apply + compile lines + NK_DONE rc=0); fix_kernel_full.log (full 33k-line build log); build.log/run.log (demonstrator).
Confirmed kernel references
Detail
Evidence (decisive lines)
run.log (26 OOB writes past the 384-byte object printed on guest); VERDICT.md source chain; fix_build.log + fix_kernel_full.log:28191 (-Werror compile of patched tonga_smumgr.c); env.txt (no AMD GPU)
PoC changes
Pass-2 reviewer authored trigger/analysis + fix from source; harness built and run on the DragonFly guest (build.log/run.log); fix compile-validated via full nativekernel rebuild.
Verified recommended fix
Clamp both loops with MIN(count, SMU72_MAX_LEVELS_GRAPHICS/MEMORY) in tonga_program_memory_timing_parameters().
Verdict
Source-certain kernel stack OOB write: tonga_program_memory_timing_parameters() indexes the 384-byte stack table arb_regs.entries[8][4] with VBIOS-controlled sclk/mclk DPM counts (u8 dep-table entries, never clamped); crafted VBIOS with >8 SCLK or >4 MCLK levels smashes up to ~15KB past the stack frame at DPM init/OD time. Guest demonstrator reproduces the exact index math (26 OOB writes for a 12x6 table); kernel path requires Tonga/Fiji hardware absent from the guest, so the in-kernel fault could not be observed - hardware-gated, matching DF-1271/1272/1280 precedent.
No comments yet.