⬢ DragonFlyBSD Kernel Audit
DF-4812 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-4812",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "leak",
  "confidence": "certain",
  "verdict": "REPRODUCED dynamically on the audit guest with the stock in-tree driver: a crafted SSDT (QEMU -acpitable) supplies the TOS6200 device whose GHCI answers Package(3) instead of the required HCI_WORDS=6; acpi_toshiba.c hci_call() (sys/dev/acpica/acpi_toshiba/acpi_toshiba.c:433-441) evaluates GHCI with ACPI_ALLOCATE_BUFFER, ACPI_PKG_VALID fails, and the function returns ENXIO at line 440 WITHOUT AcpiOsFree(results.Pointer) \u2014 every other exit frees at the end: label (460-462). Unprivileged sysctl READS of hw.acpi.toshiba.* then leak the ACPICA result buffer (M_ACPICA, Osd/OsdMemory.c:62): measured 469 objs/46.0K -> 39.5K/3.71M after 20k reads and -> 118K/11.0M after 40k more (~190B and ~1 object per hci_call; sysctl(8) makes 2 handler calls per invocation and silently swallows the error, exit 0). Unbounded -> kernel heap exhaustion DoS on any unit whose GHCI firmware returns a short package. Fix validated on the same guest: one-line AcpiOsFree before the return, module rebuilt and swapped; identical 40k-read load leaves M_ACPICA exactly flat (118K/11.0M before and after) while the invalid package! marker and allocation counters prove the same path still executes.",
  "exploit_chain": "unprivileged user loop: while :; sysctl hw.acpi.toshiba.force_fan (silent, exit 0) -> 2x hci_call -> 2x leaked ACPI_OBJECT buffers per iteration -> linear M_ACPICA exhaustion -> kernel memory starvation/DoS (no info disclosure; contents are AML-built package objects)",
  "evidence": "findings/poc/DF-4812/run.log (before/after vmstat -m rows for baseline runs 1-2 and patched run 3, dmesg marker count 40283); VERDICT.md (full path trace path:line + fix validation); ssdt_tosh.dsl/.aml (crafted table); fix_build.log (clean -Werror module build); env.txt (uname, kldstat, SSDT present, final pool state)",
  "kernel_refs": [
    "sys/dev/acpica/acpi_toshiba/acpi_toshiba.c:433",
    "sys/dev/acpica/acpi_toshiba/acpi_toshiba.c:437",
    "sys/dev/acpica/acpi_toshiba/acpi_toshiba.c:440",
    "sys/dev/acpica/acpi_toshiba/acpi_toshiba.c:460",
    "sys/dev/acpica/Osd/OsdMemory.c:62",
    "sys/dev/acpica/acpivar.h:491"
  ],
  "poc_changes": "No seed PoC (pass-2 static finding). Verification built from scratch: crafted SSDT compiled with the guests /usr/sbin/iasl, injected via QEMU_EXTRA=-acpitable (vm.sh supports the env var); unprivileged read loop via vm.sh run_user.",
  "attempts": 3,
  "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": 2100,
  "guest_dirty": 0,
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "One-line AcpiOsFree(results.Pointer) before the line-440 return; applied to guest /usr/src, module rebuilt clean (-Werror), swapped live. Baseline module: +7.3MB M_ACPICA under 40k reads; patched module under the identical load: exactly 0 growth with path markers still firing. Bad behavior GONE.",
  "fix_evidence": "findings/poc/DF-4812/fix.diff; findings/poc/DF-4812/fix_build.log; findings/poc/DF-4812/run.log (RUN 3)",
  "build_cmd": "iasl ssdt_tosh.dsl (guest) ; cd /usr/src/sys/dev/acpica/acpi_toshiba && make obj && make",
  "run_cmd": "kldload acpi_toshiba; vmstat -m|grep acpica; as unpriv user: loop 20000x sysctl hw.acpi.toshiba.force_fan; vmstat -m|grep acpica",
  "code_hash": "0bc7a849410df8fe6ac665ef4f0f81fc1dbe5780de3eaddcc6bdc623435c9743",
  "notes": "Trigger precondition is a Toshiba firmware variant returning a GHCI package with <6 elements \u2014 exactly the divergence the defensive branch was written for; supplied on the guest via a crafted SSDT so the stock driver+ACPICA executed the real kernel path. DF sysctl(8) silently ignores failed leaf reads, making the user-side trigger silent (no output, exit 0). Guest was reset to the clean-source (with-src) snapshot after the run. Related known findings not re-reported: DF-1892/1893/2393/2394.",
  "recommended_fix": "Add AcpiOsFree(results.Pointer) before the return (ENXIO) in hci_call()s invalid-package branch (acpi_toshiba.c:440)"
}