# DF-1797 — Verification Verdict

## Verdict: REPRODUCED (source-confirmed + logic-harness)

The missing bounds check is confirmed at
`sys/dev/drm/amd/powerplay/hwmgr/smu_helper.c:258,286,314` in all three
`phm_get_svi2_*_voltage_table` variants. The harness demonstrates the
256-byte heap overflow when a malicious VBIOS advertises 64 voltage
entries.

## Mechanism

`phm_get_svi2_mvdd_voltage_table` (smu_helper.c:244-270),
`phm_get_svi2_vddci_voltage_table` (272-298), and
`phm_get_svi2_vdd_voltage_table` (300-322) each set
`vol_table->count = dep_table->count` (or `lookup_table->count`) and
then loop `i = 0..count-1` writing `vol_table->entries[i]` — but
`entries[]` is fixed at `PP_ATOMCTRL_MAX_VOLTAGE_ENTRIES = 32`
(ppatomctrl.h:211). With `dep_table->count` up to a `uint32_t` (no upper
bound from VBIOS), the loop writes past `entries[31]` into whatever
follows the `pp_atomctrl_voltage_table` in its `kzalloc` allocation.

The sibling `atomctrl_get_voltage_table_v3` (ppatomctrl.c:526-551)
DOES bound-check `ucGpioEntryNum <= PP_ATOMCTRL_MAX_VOLTAGE_ENTRIES`
before its equivalent loop (:546-551) — proving the bound is required
and simply missing from the SVI2 helpers.

## Harness evidence

```
DF-1797: phm_get_svi2_vdd_voltage_table wrote 32 entries past entries[32] (count=64 max=32) -> 256 bytes of trailing memory corrupted (sentinel bytes touched=256)
Matches smu_helper.c:314 (count=lookup->count) + :317 (entries[i]=..) with no bound; contrast ppatomctrl.c:546-551 which DOES check.
```

## Why no live trigger on this guest

`phm_get_svi2_*_voltage_table` is called from AMD GPU PowerPlay init
when parsing VBIOS voltage tables. The audit guest has no AMD GPU
(`amdgpu.ko` is present but not loaded, no HW). A malicious/flashed
VBIOS on a PCIe GPU or VFIO passthrough is the live trigger. Valid
Phase-6 hard blocker.

## Exploit chain

Not applicable (AMD-GPU-gated). No `uid=0` claim. Live ceiling on real
HW: panic / 256+ byte heap corruption in PowerPlay init; potentially
escalatable against objects in the same slab bucket.

## PoC changes

- Added `harness.c`: flat-buffer model showing 32 OOB entry writes.
- Added `fix.diff`: add `if (count > PP_ATOMCTRL_MAX_VOLTAGE_ENTRIES)
  return -EINVAL;` to each of the three helpers.

## Fix

`fix.diff` adds the missing bounds check before each loop, mirroring
ppatomctrl.c:546-551.

- BEFORE: harness reports 256 bytes of trailing memory corrupted (count=64).
- AFTER: the check rejects count > 32 before any write.
