# DF-1167 — VERDICT

**Verdict: REPRODUCED (source+harness).** Not `uid=0`-escalatable — this is a
**NULL-deref / OOB-read DoS** in optional GPU firmware-parsing code.

## Bug confirmation

`smu7_setup_dpm_tables_v0()` at
`sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c:666` reads
`std_voltage_table = hwmgr->dyn_state.cac_leakage_table` at lines 673-674 with
**no NULL check**, then in the loop at lines 716-721 indexes
`std_voltage_table->entries[i].Leakage` bounded by
`allowed_vdd_sclk_table->count` — **not** by `std_voltage_table->count`.

The pointer is provably NULL on a common path:
`sys/dev/drm/amd/powerplay/hwmgr/processpptables.c:1470` unconditionally sets
`hwmgr->dyn_state.cac_leakage_table = NULL;` and only assigns a real table at
line 1476 when `ptable5->usCACLeakageTableOffset != 0` (line 1472). A
PowerPlay table that omits the CAC leakage table therefore leaves the pointer
NULL, and the next call into `smu7_setup_dpm_tables_v0` dereferences NULL at
line 718 (`std_voltage_table->entries[i].Leakage`) → **kernel panic**.

Even when the table is present, if its `count` is smaller than
`vddc_dependency_on_sclk->count`, the same loop performs an **out-of-bounds
read** past the `kzalloc`'d `cac_leakage_table` (allocated at
`processpptables.c:1382` with size derived from the table's own
`ucNumEntries`).

The mandatory-table assertions at lines 677-685 cover `allowed_vdd_sclk_table`
and `allowed_vdd_mclk_table`, but **no** assertion guards `std_voltage_table`,
confirming the reviewer's claim.

## Reproducibility on the audit guest

- `amdgpu`/`radeon`/`powerplay` are `optional` (`sys/conf/files:2492+`); they
  are **not compiled into `X86_64_GENERIC`** (the running `#0` kernel) and the
  QEMU guest has **no AMD GPU**.
- `amdgpu.ko` exists in `/boot/modules/` but cannot initialize the powerplay
  path without real AMD GPU hardware, so a live kernel trigger is not possible
  on this guest.

A userspace harness (`harness.c`) reconstructs the exact struct layouts from
`hwmgr.h` and replays the loop at `smu7_hwmgr.c:716-721`. Run on the guest
(`./build.sh && ./run.sh`) it demonstrates **both** primitive classes:

```
[case 1] std_voltage_table=NULL, sclk_count=3 -> reproducing kernel loop...
  BUG: dereferenced std_voltage_table (NULL) at i=0
  harness: caught signal 11 (SIGSEGV/SIGBUS) -- kernel equivalent: NULL-deref panic

[case 2] std_voltage_table->count=1, sclk_count=8 -> OOB read
  i=1..7: BUG OOB read std_voltage_table->entries[i].Leakage (past allocated count=1)
```

Because this is a **read** primitive (NULL deref / OOB read), there is no
memory-corruption **write** to convert into `uid=0`. The realistic impact
ceiling is a **kernel panic / DoS** at driver attach time, plus a small info
leak (OOB kernel heap read into the `param1` field of the DPM table, which is
later exposed through the PowerPlay sysfs/debugfs interface on a real GPU
system).

## Exploit chain

`none` — not a write primitive. DoS ceiling documented above.

## Fix

`fix.diff` adds the missing NULL check (`std_voltage_table != NULL`) and the
missing bounds check (`i < std_voltage_table->count`) to the loop, defaulting
`param1` to 0 when the std voltage entry is absent. The diff `git apply --check`s
cleanly against the audit tree.

## Threat model

The PowerPlay table is parsed from the GPU VBIOS / ACPI `powerplay` table at
driver attach time. An attacker who can supply a crafted VBIOS (re-flashed GPU,
malicious PCI device, or a hypervisor/emulator presenting a forged AMD GPU)
triggers an immediate kernel panic at boot or module load. Severity Medium for
the default GENERIC kernel (module not loaded), High for any system that
actually loads `amdgpu`.
