# DF-3940 — VERDICT

**Status: inconclusive (hardware-gated) — source-level certainty: certain.**
**Impact class: kernel heap out-of-bounds write (CWE-787), crafted-VBIOS vector.**

## What overflows, exactly

`struct ci_smumgr` is `kzalloc`'d at `ci_smumgr.c:2731-2743`; it embeds
`SMU7_Discrete_DpmTable smc_state_table` (with `MemoryLevel[6]` at
`smu7_discrete.h:325`) and, near its tail, `SMU7_Discrete_MCRegisters mc_regs`
(with `data[6]` since `SMU7_DISCRETE_MC_REGISTER_ARRAY_SET_COUNT ==
SMU7_MAX_LEVELS_MEMORY`, `smu7_discrete.h:408`). For CI,
`SMU7_MAX_LEVELS_MEMORY == SMU__NUM_MCLK_DPM_LEVELS == 6`
(`ci_smumgr.h:27`) while the hwmgr-side DPM machinery holds up to
`MAX_REGULAR_DPM_NUMBER == 8` levels (`smu7_hwmgr.h:95,100`).

Sinks (all keyed on `dpm_table->mclk_table.count`, never clamped):

| # | site | write | OOB when count |
|---|---|---|---|
| 1 | `ci_smumgr.c:1314-1318` | full `SMU7_Discrete_MemoryLevel` (~40B, ~30 VBIOS-derived fields) per level via `ci_populate_single_memory_level` | 7 or 8 |
| 2 | `ci_smumgr.c:1339` | `[count-1].DisplayWatermark` u8 | 7 or 8 |
| 3 | `ci_smumgr.c:1794-1798` | `SMU7_Discrete_MCRegisterSet` (16 x u32 VBIOS MC data) per level into `mc_regs->data[i]` | 7 or 8 |
| 4 | `ci_smumgr.c:2819-2846` | `ActivityLevel` (u16), `UpH`/`DownH` (u8) via `MemoryDpmLevelCount` (set at `:1337`) | 7 or 8 |

Writes stay **inside** the `ci_smumgr` allocation for sinks 1-2 (they land on
`LinkLevel[0..2]`) and reach the trailing `ci_mc_reg_table` for sink 3 —
in-object corruption of the heap object that is then byte-copied wholesale
into SMC RAM (`ci_copy_bytes_to_smc`, bounded to SMC_RAM_END, so no kernel
side-effect there). This is precisely the DF-3909 (tonga) result shape: heap
object corruption with attacker-influenced contents, gateway to
confused SMC firmware state and, with the right heap layout, past-object
corruption is *not* reachable from these sinks alone (struct is large and the
sinks are mid/tail members; sink 3's `data[7]` ends 64B into `ci_mc_reg_table`).

## Count provenance (path:line)

- `processpptables.c:391` — count = VBIOS `ucNumEntries` (u8, ≤255).
- `hwmgr.h:120-123` — dep table entries[1] dynamic alloc → any count fits the *source* table.
- `smu7_hwmgr.c:704-710` — v0 setup (CI selects PP_TABLE_V0 at `hwmgr.c:92-99`) dedups into `dpm_levels[8]`; count 7-8 in-bounds; **no trim to 6**.
- Contrast (proves the omission is the bug, not policy):
  - voltage tables trimmed: `smu7_hwmgr.c:324-346` (`phm_trim_voltage_table_to_fit_state_table` + `smum_get_mac_definition(SMU_MAX_LEVELS_{VDDC,VDDGFX,VDDCI,MVDD})`) — hence `VddcLevel[8]`/`VddciLevel[4]`/`MvddLevel[4]` writes at `ci_smumgr.c:839-922` are SAFE (negative result).
  - PCIE table capped: `smu7_hwmgr.c:557-569` (`max_entry = min(SMU7_MAX_LEVELS_LINK, count)`, `count = max_entry - 1` ≤ 7) — hence the `i <= count` loop at `ci_smumgr.c:1003` writing `LinkLevel[count]` stays ≤ `LinkLevel[7]`, in-bounds (negative result — looks like an off-by-one, is not reachable for CI).

## Why not reproduced

No AMD GPU on the audit guest (env.txt). Requires Bonaire/Hawaii hardware
plus a modified VBIOS image. Classified `inconclusive` per batch convention
(DF-3934/DF-3935, tonga DF-3908..3910). No uid=0 chain possible without the
device; the write contents are largely VBIOS-chosen (clocks, voltages, MC
register values) making this a strong corruption primitive on-target.

## Fix validation

`fix.diff` clamps the MCLK count at the populate sinks (sinks 1, 2, 4 via the
clamped `count`, sink 3 with its own clamp). `fix_status: not_testable`
(no hardware); bounds-only diff. Root fix belongs one layer up — trim MCLK
(and SCLK for symmetry) in `smu7_setup_dpm_tables_v0/v1` exactly like the
voltage/PCIE tables; that also kills DF-3939's trigger at the source.

## Out-of-file note (for the orchestrator, not re-reported here)
Dep-table counts > 8 overflow `dpm_levels[8]` inside `struct smu7_hwmgr`
itself (`smu7_hwmgr.c:704-710`, `:783-799`) — a separate file/finding.

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