⬢ DragonFlyBSD Kernel Audit
DF-5074 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5074",
  "status": "untested",
  "reproduced": false,
  "impact": "none",
  "confidence": "certain",
  "verdict": "Code defect certain, structurally untriggerable on any stock configuration. acpi_acad installs an ACPI_ALL_NOTIFY handler with context=dev (acpi_acad.c:193-194), a global ACPIIO_ACAD_GET_STATUS ioctl hook (acpi_acad.c:172), and the hw.acpi.acline sysctl OID pinning &sc->status (acpi_acad.c:180-183), but its methods table (acpi_acad.c:76-82) has NO device_detach. Because a missing method makes DEVICE_DETACH return ENXIO (subr_kobj.c:69-75) and devclass_delete_driver aborts on the first detach failure (subr_bus.c:901-902), the acad softc can never be freed \u2014 so, unlike DF-5006 (where bus_generic_detach succeeded and freed the softc), no UAF materializes. Real-world effect: the three registrations are pinned forever and kldunload of a modular acpi.ko is permanently blocked on any machine with an AC adapter; any future bare detach-that-returns-0 converts it into the DF-5006-class UAF. Unprivileged reachability: none.",
  "exploit_chain": "",
  "evidence": "VERDICT.md (full newbus/kobj mechanics with path:line proving the softc can never be freed); run.log (guest gate: no ACPI0003 on stock QEMU DSDT so acad never attaches; acpi compiled into kernel so kldunload acpi -> cant find file; no devctl utility); fix.diff (real acpi_acad_detach: AcpiRemoveNotifyHandler + acpi_deregister_ioctl + sysctl_remove_oid)",
  "kernel_refs": [
    "sys/dev/acpica/acpi_acad.c:76",
    "sys/dev/acpica/acpi_acad.c:172",
    "sys/dev/acpica/acpi_acad.c:180",
    "sys/dev/acpica/acpi_acad.c:183",
    "sys/dev/acpica/acpi_acad.c:193",
    "sys/dev/acpica/acpi_acad.c:195",
    "sys/dev/acpica/acpi_acad.c:140",
    "sys/kern/subr_bus.c:2139",
    "sys/kern/subr_bus.c:901",
    "sys/kern/subr_kobj.c:69"
  ],
  "poc_changes": "No seed PoC (new pass-2 finding). No trigger program written because the cited path is dead at runtime on this guest and on stock systems \u2014 documented instead (run.log).",
  "attempts": 0,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026     root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC  x86_64",
  "runtime_sec": 60,
  "guest_dirty": 0,
  "build_cmd": "none",
  "run_cmd": "dfbsd-qemu/vm.sh run_root sysctl hw.acpi.acline; kldstat; kldunload acpi; which devctl   (gate documentation, see run.log)",
  "code_hash": "n/a",
  "notes": "DF-5006 family (acpi_cpu) but mirror-image flavor: DF-5006 = detach succeeds without cleanup -> live UAF on modular unload; DF-5074 = no detach at all -> nothing freed -> pinning + unload-blocking + latent hazard. Also folded: ignored AcpiInstallNotifyHandler return at :193 and undrained AcpiOsExecute work (:140,:195) \u2014 both moot until a detach exists and both handled by fix.diff (AcpiRemoveNotifyHandler drains ACPICA-internal notify work).",
  "recommended_fix": "Add acpi_acad_detach that removes the ACPI_ALL_NOTIFY handler, deregisters ACPIIO_ACAD_GET_STATUS, and removes the unit-0 acline sysctl OID tracked in the softc (fix.diff).",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": null,
  "fix_verdict": "No triggerable baseline exists (untested verdict) so a fix build has nothing to validate against; fix.diff follows the exact attach registrations reversed and is not applied to sys/.",
  "fix_evidence": "n/a \u2014 no runtime baseline possible; structural analysis in VERDICT.md."
}