# DF-5006 VERDICT — UNTESTED (gated: privileged unload + module-built acpi); code defect certain

**What is certain (code):** acpi_cpu.c installs an ACPI notify handler with
`sc` as context (acpi_cpu.c:252), two sysctl contexts (:171, :180) that the
children also hang handlers on (acpi_cpu_cstate.c:759-774), and a sensordev
(:233), and provides **no teardown**: `device_detach` is bare
`bus_generic_detach` (acpi_cpu.c:67). Newbus frees the softc on driver
detach (sys/kern/subr_bus.c:1941-1944), after which (a) any
`Notify(.,0x80/0x81)` from AML dispatches `acpi_cpu_notify` (:324-342) over
a freed softc — read of `sc->cpu_cst_notify`/`sc->cpu_pst_notify` and call
through it = use-after-free; (b) `hw.acpi.cpu.cx_lowest`-style sysctls
resolve handlers whose ctx pointers reference freed softc memory; (c) the
sensordev stays globally registered. Attach error paths (:236-237,
:243-244) leak the same resources without any detach at all.

**Why not exercised on the guest:** the only route to this driver's detach
is unloading an acpi.ko built as a module — a privileged, non-default
configuration. On the audit guest acpi is compiled into the kernel
(`env_probe.txt`: `kldunload acpi` → "can't find file acpi"), so the
path is unreachable there; no unprivileged or remote trigger exists. Per
contract (Low severity, privileged-only), no PoC was attempted — status
`untested`, not a refutation.

**Reachability detail for maintainers:** the notify-pointer protocol is
attach-order-safe today (`bus_generic_attach` at :250 precedes
`AcpiInstallNotifyHandler` at :252, and children set the pointers in their
attach — acpi_cpu_cstate.c:751, acpi_cpu_pstate.c:810) — the UAF needs the
driver/module teardown that this driver simply doesn't implement. FreeBSD's
acpi_cpu grew a proper detach (AcpiRemoveNotifyHandler + sysctl_ctx_free +
sensordev_deinstall) years ago; DragonFly's 2008 import never got it.

**Fix:** `fix.diff` — `acpi_cpu_detach` (remove handler first, then detach
children, then free both contexts, then deinstall sensordev) + attach
error-path cleanup (delete orphaned cpu_cst child, free contexts,
deinstall sensordev). Not validated on the guest (path unreachable there);
kernel-build of this diff is straightforward (no API changes) but was not
performed since the guest cannot reach the code path either way.

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