# DF-4426 VERDICT — UINT8 instance wraparound → infinite loop under `hp` lock

## Reproduced?
**On-guest kernel reproduction: no** — the audit guest (QEMU/SeaBIOS, no HP
BIOS) has no PNP0C14 ACPI node, so `acpi_wmi` never attaches
(`env.txt`: no `/dev/wmistat*`, no `hw.acpi.wmi` sysctl), and `acpi_hp`
consequently never creates `/dev/hpcmi` (`env.txt`: no `/dev/hpcmi`, no
`hw.acpi.hp` sysctl oid). The defect requires a physical HP WMI BIOS whose
CMI GUID advertises `max_instance == 254`.

**Logic-level reproduction: YES, on the DragonFly guest itself** — the exact
loop control flow from acpi_hp.c:1164-1204 was extracted verbatim into
`wrap_harness.c` (only the WMI layer stubbed; `UINT8` = `unsigned char`
identical on DFly x86-64), compiled with DragonFly cc 8.3 **on the guest**,
and run (`run.log`):

- error at instance 0 → **300,000 body executions, 0 inserts** — a pure
  infinite loop with zero memory writes. In-kernel this pins the calling
  thread inside `dev_read` forever while it holds
  `lockmgr(&hp_serial, LK_EXCLUSIVE|LK_RETRY)` (acpi_hp.c:1157,
  acpivar.h:170) — every later `hw.acpi.hp.*` sysctl op and every
  `/dev/hpcmi` open blocks forever. Unprivileged local DoS (device is 0644,
  acpi_hp.c:523-524).
- error at instance 5 → **unbounded restart**: cmi_order_size reached
  250,000 in the capped demo — in-kernel this drives `cmi_order[128]` OOB
  writes far beyond what DF-2382 describes (which covers >128 *instances*;
  here a *single* broken instance at k causes infinite re-appending of k
  entries per wrap).
- no error → normal 255-iteration termination (control run).

## Root cause (path:line)
- `sys/dev/acpica/acpi_hp/acpi_hp.c:1172` — `for (instance = 0; instance <
  maxInstance; ++instance)` with `UINT8 instance` (declared :1145).
- `sys/dev/acpica/acpi_hp/acpi_hp.c:1178` — `instance = maxInstance;` as the
  error-break idiom; with `maxInstance == 255`, `++instance` wraps to 0 and
  the loop restarts (`UINT8` arithmetic).
- `maxInstance == 255` requires `sc->has_cmi == 255` (WMI GUID
  `max_instance == 254`, returned as `max_instance+1` by
  acpi_wmi.c:344) **and** `ACPI_HP_CMI_DETAIL_SHOW_MAX_INSTANCE` set in
  `hw.acpi.hp.cmi_detail` (sysctl root-writable only —
  kern_sysctl.c:1446 `SYSCAP_NOSYSCTL_WR` check), which skips the
  `maxInstance--` at acpi_hp.c:1168.

## Why the guest can't show the kernel manifestation
No WMI firmware. Injecting a crafted PNP0C14 SSDT into the QEMU firmware is
out of scope for a Low-severity finding; the loop logic itself is fully
characterized and the lock-held-forever consequence is structural (the whole
enumeration runs between `ACPI_SERIAL_BEGIN(hp)`/:1157 and
`ACPI_SERIAL_END(hp)`/:1229).

## Exploit chain
(none — denial of service only: stuck kernel thread + permanently held
global `hp` sx/lockmgr lock; repeatable by any user once the sysctl
precondition is set, e.g. `sysctl hw.acpi.hp.cmi_detail=8` then
`cat /dev/hpcmi` on a matching BIOS.)

## Fix
`fix.diff` (dry-run verified): replace the `instance = maxInstance` idiom
with a `stop` flag + `break`. One-line semantic fix; keeps the loop variable
wrap-proof.

## Fix validation
not_testable — no HP WMI hardware on the guest; the fix is a control-flow
change whose logic effect is directly visible in the harness (with the fix
applied to the harness loop, all three runs terminate).

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