# DF-3888 — verdict narrative

## Finding

`kv_parse_power_table` only sets `ps->num_levels` inside
`kv_parse_pplib_clock_info` (kv_dpm.c:2694: `ps->num_levels = index + 1`), which is
called only for **valid** clock entries — the state loop `continue`s on
`clock_array_index >= clock_info_array->ucNumEntries` (:2758-2759) and `break`s at
`k >= SUMO_MAX_HARDWARE_POWERLEVELS` (:2760). A VBIOS state with
`ucNumDPMLevels == 0`, or whose `clockInfoIndex[]` entries are all out of range,
therefore leaves the `kzalloc`-zeroed `struct kv_ps` with **`num_levels == 0`** —
parse-legal, no error.

Use sites then compute `levels[num_levels - 1]` with unsigned `num_levels` (u32):

- `kv_dpm_get_sclk` (kv_dpm.c:2929-2939):
  `return requested_state->levels[requested_state->num_levels - 1].sclk;` (:2938)
  → `levels[0xFFFFFFFF]` → `levels + 51,539,607,540` bytes (~48 GB) — wild read.
  `requested_state` is `kv_get_ps(&pi->requested_rps)`; after any power-state
  selection that lands on a 0-level state, `pi->requested_ps.num_levels == 0`.
- `kv_set_valid_clock_range` (:1772-1832): `new_ps->levels[new_ps->num_levels - 1].sclk`
  at :1791 (vddc-table branch) and :1817 (sumo-table branch) — same wild read, plus
  the comparison chain at :1797-1798/:1822-1826 reads `table->entries[highest_valid]`
  with a `highest_valid` derived from the poisoned loop.

Impact: page fault in kernel mode → panic (the ~48 GB offset is never mapped);
not a leak (value unusable). DoS.

**Trigger reach:** on a machine whose (crafted) VBIOS contains such a state, the
read is reachable **unprivileged**: the `AMDGPU_INFO` ioctl
(`AMDGPU_INFO_DEV_INFO` → `amdgpu_dpm_get_sclk(adev, false)`, amdgpu_kms.c:700,
`DRM_IOCTL_DEF_DRV(AMDGPU_INFO, ..., DRM_AUTH|DRM_RENDER_ALLOW)` :1207) — i.e. any
user holding the render node; also every DCE8 modeset (dce_v8_0.c:971).
The `kv_set_valid_clock_range` sink additionally needs the state to survive
`kv_check_state_equal` (kv_dpm.c:3261: differs from current → first transition).

This is the count-1-underflow family already filed for the powerplay hwmgrs
(DF-3686 smu7, DF-3858 vega20); `kv_dpm.c` is the legacy-DPM twin, unfixed here.

## Root cause (kernel references)

- `sys/dev/drm/amd/amdgpu/kv_dpm.c:2938` — `levels[num_levels - 1]` in get_sclk
- `sys/dev/drm/amd/amdgpu/kv_dpm.c:1791`, `:1817` — same in set_valid_clock_range
- `sys/dev/drm/amd/amdgpu/kv_dpm.c:2694` + `:2756-2769` — num_levels only set for valid entries
- `sys/dev/drm/amd/amdgpu/amdgpu_kms.c:700` — unprivileged ioctl caller

## What was verified, and how

1. **Source-level certainty.** Full-file pass-2 audit; struct geometry
   (`struct kv_pl` = 12 bytes, `levels[5]`) from kv_dpm.h; caller chain verified in
   amdgpu_pm.c (`amdgpu_dpm_change_power_state_locked` :1895-1945 → pre_set →
   check_state_equal → set_power_state) and amdgpu_kms.c (ioctl flags :1207).
2. **Harness on the guest** (DragonFly 6.5-DEVELOPMENT x86_64, base cc 8.3):
   `num_levels_underflow.c` replicates `kv_dpm_get_sclk` verbatim with 1:1 layouts.
   Accounting mode prints index `4294967295`, offset `51539607540` bytes (~51.5 GB);
   crash mode executes the verbatim read against a single-page mapping → SIGSEGV
   exit=139 (kernel equivalent: page fault in kernel mode → panic).
3. **Hardware absence.** Guest is virtio-only; no AMD GPU, amdgpu not loaded. The
   in-kernel trigger needs a Kaveri/Kabini/Mullins APU with a crafted VBIOS.
   Recorded **inconclusive**, impact none *on this guest* (per pass-2 spawn
   instructions), source + harness: certain.

## Fix validation

`fix.diff` guards `num_levels == 0` (and NULL priv) in `kv_dpm_get_sclk` and adds an
early return in `kv_set_valid_clock_range`. Not built on the guest (no AMD hardware)
→ `fix_status: not_testable`.

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