# DF-3909 — Tonga/Fiji SMC state table: heap OOB writes into GraphicsLevel[8] / MemoryLevel[4] via unclamped VBIOS DPM counts

**File:** `sys/dev/drm/amd/powerplay/smumgr/tonga_smumgr.c`
**Lines:** 709-742, 1673-1675 (`tonga_populate_all_graphic_levels`, clock stretcher read), 1107-1133 (`tonga_populate_all_memory_levels`)
**Severity:** High (kernel heap corruption) — **hardware-gated** (Tonga/Fiji + crafted VBIOS)
**Class:** memcorrupt / CWE-787, pass 2 (checklist items (a)/(e): the graphic/memory level tables the knowns did not touch)

## Build / Run
```
./build.sh && ./run.sh
```

## Expected output
```
GraphicsLevel[8] span        : 512 bytes
sclk dep count (VBIOS u8)    : 16
OOB GraphicsLevel writes     : 8, worst write ends at GraphicsLevel+1024
  -> stomps MemoryACPILevel/MemoryLevel[4]/LinkLevel[8]/... (intra-struct)
MemoryLevel[4] span          : 384 bytes; mclk count 9
OOB MemoryLevel writes       : 5 (worst ends at +864); watermark store at +768 (also OOB)
count==0 form                : MemoryLevel[(uint32)(0-1)] = wild write at +4294967295*96
trigger rc=1 (1 == OOB index math demonstrated)
```

## Root cause
Same unclamped `dpm_table->sclk_table.count` / `mclk_table.count` driver as
DF-3908, but the sinks are the **heap** arrays inside the kzalloc'd
`struct tonga_smumgr` (tonga_smumgr.h:66):
- `smc_state_table.GraphicsLevel[SMU72_MAX_LEVELS_GRAPHICS=8]` — loop at
  :709-712 writes `GraphicsLevel[i]` for i < count; :726 watermark store at
  `GraphicsLevel[count-1]`; :740/:769 pcieDpmLevel stores; the clock
  stretcher additionally READS `GraphicsLevel[GraphicsDpmLevelCount-1]`
  (:1673-1675).
- `smc_state_table.MemoryLevel[SMU72_MAX_LEVELS_MEMORY=4]` — loop at
  :1107-1114; boot-level watermark store at `MemoryLevel[count-1]` (:1133)
  is additionally unguarded against count==0 (wild index 0xFFFFFFFF; only
  reachable if a setup failure is ignored per DF-3686).
GraphicsLevel is followed in-struct by MemoryACPILevel, MemoryLevel[4],
LinkLevel[8], ACPILevel, UvdLevel[8], VceLevel[8], AcpLevel[8] … so counts
9..255 corrupt the rest of the uploaded SMC tables and, past ~5 KB, run
beyond the allocation entirely.
Distinct from knowns: DF-1271 = UvdLevel/VceLevel/AcpLevel via mm_dep count;
DF-1272 = Sclk_voltageOffset[8] via vdd_dep_on_sclk count; neither touches
the GraphicsLevel/MemoryLevel arrays.

## Fix
`fix.diff` clamps sclk_count/mclk_count to the array bounds at every use
(including GraphicsDpmLevelCount/MemoryDpmLevelCount and the count-1
stores). Validated: applied on guest `/usr/src`, full nativekernel rebuild
rc=0, `-Werror` clean (fix_build.log; full log in ../DF-3908/fix_kernel_full.log:28191).
