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