# DF-5622 VERDICT — reachable KKASSERT panic on firmware `_PSS` data (amd0f_set_fidvid)

**Status: not_reproduced (on this guest) — static path CERTAIN, trigger hardware absent.**
**Impact class if triggered: kernel panic (DoS) — no memory-corruption primitive.**

## Reproduced?

No — and it is architecturally impossible on the audit guest, which I prove live
rather than assert. What I *did* verify on the guest (see `run.log`):

1. The amd0f helpers are **compiled into the running stock GENERIC kernel**
   (`nm /boot/kernel/kernel` → `amd0f_set_fidvid` @ 0xffffffff80bda6c0,
   `amd0f_get_fidvid`, `amd0f_fidvid_limit`; KLD `kldstat` + symbol addresses
   via the harness). The file is live code (sys/platform/pc64/conf/files:149
   `standard`), *not* part of the dead `#ifdef notyet` legacy CPU attachment
   (sys/bus/pci/x86_64/legacy.c:233-347) that DF-5572 covers.
2. The running kernel is built from `X86_64_GENERIC` (uname build path
   `/usr/obj/usr/src/sys/X86_64_GENERIC`) and that config has
   `options INVARIANTS` at line 56 → `KKASSERT` is a live `panic()`
   (sys/sys/systm.h:98-101), not a no-op.
3. The live KLD harness `pstprobe.c` calls the real exported kernel function
   `acpi_pst_md_probe()` and dumps the gating facts:
   guest CPU vendor = 0x8086 (Intel), APMI(0x80000007) EDX = 0, probe returns
   NULL. Both gates for `acpi_pst_amd0f` (vendor==AMD **and**
   `(APMI_edx & 0x06) == 0x06`, acpi_pstate_machdep.c:150-175) are OFF.
   `amd0f_set_fidvid` therefore cannot execute on this guest. QEMU/KVM does
   not implement K8 FID/VID MSRs (0xc0010041/0xc0010042) in any configuration
   this harness can reach; even calling the global symbol directly would #GP
   at the entry `rdmsr` (cpufreq_machdep.c:78) — the DF-5484 class, already
   filed for the sibling file — before ever reaching the asserts at
   cpufreq_machdep.c:92/94.

## Why the finding is still certain (line-by-line trace)

Attacker-controlled (firmware) value flow into the asserted expressions:

- `_PSS` package → `acpi_pstates[i].st_cval` (sys/dev/acpica/acpi_cpu_pstate.c:585)
  → attach-time validation `acpi_pst_amd0f_check_pstates()`
  (acpi_pstate_machdep.c:288-368):
  - entry i==0 (max state): FID/VID vs MSR-derived limits — **kprintf only,
    never EINVAL** (acpi_pstate_machdep.c:310-320);
  - entry i==npstates-1 (min state): **kprintf only** (lines 321-331);
  - middle entries: EINVAL only if `acpi_pst_stringent_check` (default 1, but a
    boot tunable, and irrelevant to the endpoints) — lines 332-347;
  - `mvs != 0` → hard EINVAL (line 353) ⇒ mvs is always 0 at runtime;
  - `rvo_mv % mvs_mv` check (line 361) is vacuous for mvs==0
    (25*rvo % 25 == 0 for every rvo ∈ 0..3) ⇒ **rvo is never constrained**.
- Transition (first `acpi_pst_postattach` transition, `powerd`, or root sysctl
  write — writes need `SYSCAP_NOSYSCTL_WR`, sys/kern/kern_sysctl.c:1446)
  → `acpi_pst_amd0f_set_pstate()` (acpi_pstate_machdep.c:370-388) packs
  `fv.fid/fv.vid` and `xsit.rvo/mvs/vst/pll_time/irt` straight from `st_cval`
  → `amd0f_set_fidvid()`.
- cpufreq_machdep.c:91: frequency-increase (or vid-lowering) branch evaluates
  `KKASSERT(fv->vid >= xsit->rvo)` → panics for e.g. endpoint entry with
  vid=0, rvo=3. cpufreq_machdep.c:94: `KKASSERT(cvid >= xsit->rvo)` fires on a
  downgrade when hardware sits at cvid < rvo (K8 boots at max voltage = low
  cvid value). Both are `panic()` under the stock INVARIANTS kernel.

No bounds/type error exists in the value flow (fid 6 bits, vid 5 bits, rvo 2
bits — all masked at extraction), so on a *non*-INVARIANTS kernel the same
malformed table instead programs slightly out-of-sequence VID steps (bounded
loops, clamped by `cvid > 0` guards) — the kernel-safety impact is exactly the
assert-panic; there is no memory-corruption primitive (no arrays, no pointers,
no copyout in the entire file).

## Threat model honesty

The only actor who can supply a malformed `_PSS` is firmware/BIOS or the
hypervisor owner (host). A guest unprivileged user has **no** path: the sysctl
surface is root-only and can only select among already-attached states. Hence
Low severity, and no uid0 escalation chain exists for this bug class.

## Fix

`fix.diff` (authored post-verification, never applied to `sys/`): converts both
asserts to `return EINVAL`. Fix validation (`fix_status`) is `not_testable`:
the baseline panic cannot be produced on this guest (hardware gate above), so
no patched-kernel A/B run is meaningful.

## Artifacts

- `pstprobe.c`, `Makefile`, `build.sh`, `run.sh` — live-introspection KLD harness
- `build.log` — full untrimmed successful KLD build (-Werror, gcc DF 6.5)
- `run.log` — kldload + dmesg + INVARIANTS config line
- `env.txt` — guest environment
- `fix.diff` — validated-by-inspection one-hunk fix
- `manifest.json`, `verdict.json`

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