⬢ DragonFlyBSD Kernel Audit
DF-5545 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5545",
  "status": "reproduced",
  "reproduced": true,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "xhci_pci_detach() discards device_delete_children()s return at sys/bus/u4b/controller/xhci_pci.c:355 and unconditionally halts the controller, tears down the interrupt, releases IRQ+MMIO, frees all USB DMA via xhci_uninit (:378) and returns 0 (:380). Demonstrated live on the QEMU guest with a real xHCI controller: with one child vetoing detach, device_detach(xhci0) reported complete success (xhci0: detached), left the vetoing child ATTACHED to the now-driverless xhci0 whose softc had been kfreed/NULLed by device_set_driver(dev,NULL) (subr_bus.c:2156) -- the next touch of the parent context through the orphan was a Fatal trap 12 page fault (NULL softc + 0x20 field offset, Stopped at df5545_thread+0x91 movq 0x20(%rax),%rdx), guest dead in DDB. The vetoing child is a KLD stand-in for the newbus detach contract (no in-tree u4b child detach returns nonzero today; usb_detach returns 0 unconditionally at usb_controller.c:242) -- exact family recurrence of DF-5544 (uhci, proven identically this pass), DF-5528 (fwohci) and DF-4558 (atapi-cam). Root-context trigger (kldunload/PCI hot-unplug) => Low severity; mechanics certain. fix.diff (check + propagate return) validated on a rebuilt guest kernel (combined with the DF-5546 fix, one rebuild): identical trigger now returns 16 with refusing controller teardown, driver bound, state DS_ATTACHED, ring/DCBAA DMA buffers byte-identical, no panic on the touch that killed the baseline; a later retry after the child cooperates completes a clean 0-children detach.",
  "exploit_chain": "privileged: kldunload xhci / PCI hot-unplug -> devclass_delete_driver (subr_bus.c:897) -> device_detach(xhci0) -> xhci_pci_detach -> device_delete_children fails (child veto at subr_bus.c:1292) -> return value discarded -> IRQ/MMIO released, xhci_uninit frees event+command ring, DCBAA and scratchpad DMA pages, returns 0 -> device_set_driver(NULL) kfrees softc, device_get_softc(xhci0) becomes NULL -> still-attached child operates on freed/NULL parent state -> supervisor page fault (observed) / UAF reads of freed DMA pages (harness cmd3). Not reachable by an unprivileged user through this file.",
  "evidence": "panic.txt (raw serial: veto -> xhci0: detached -> returned 0 -> veto0(attached=1) -> Fatal trap 12 fault va=0x20, Stopped at df5545_thread+0x91 movq 0x20(%rax),%rdx); serial_console_full.log; run.log (baseline transcript + root-cause chain); run.fix.log (patched: child device failed to detach; refusing controller teardown, returned 16, driver=xhci state=3, ring/DCBAA buffers unchanged, guest alive; cooperate retry -> clean 0-children detach); veto.c/Makefile/build.sh/run.sh (harness); build.log; fix_build.log (xhci_pci.c recompiled, installkernel completed, kernel md5 29a0c51c2e9202a724a7b626b3416d39); env.txt; fix.diff",
  "kernel_refs": [
    "sys/bus/u4b/controller/xhci_pci.c:355",
    "sys/bus/u4b/controller/xhci_pci.c:372",
    "sys/bus/u4b/controller/xhci_pci.c:378",
    "sys/bus/u4b/controller/xhci_pci.c:380",
    "sys/kern/subr_bus.c:1292",
    "sys/kern/subr_bus.c:2156",
    "sys/kern/subr_bus.c:897",
    "sys/bus/u4b/controller/usb_controller.c:242",
    "sys/bus/u4b/controller/xhci.c:675"
  ],
  "poc_changes": "Adapted the proven DF-5544 uhci harness to xhci (DRIVER_MODULE(veto, xhci, ...), snapshot of sc_hw.root_pc/sc_hw.ctx_pc DMA pages instead of uhci frame list, MSI/polling-agnostic). Guest booted with QEMU_EXTRA=-device qemu-xhci (vm.sh default has no USB); xhci is compiled into X86_64_GENERIC so the kldunload path was driven via device_detach() from a module kernel thread, identical to devclass_delete_driver(). Baseline panic on hw.df5545=2 exactly as predicted; fix run on the combined-fix rebuilt kernel.",
  "attempts": 2,
  "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 (baseline; fix validated on rebuilt kernel installed Wed Oct  7 09:43:48 UTC 2026, md5 29a0c51c2e9202a724a7b626b3416d39)",
  "runtime_sec": 2340,
  "guest_dirty": 0,
  "build_cmd": "cd /root/df5545 && make KERNBUILDDIR=/usr/obj/usr/src/sys/X86_64_GENERIC",
  "run_cmd": "kldload /root/df5545/veto.ko; sysctl hw.df5545=1; sysctl hw.df5545=2",
  "code_hash": "5a3901e90e21e271a3456e45e2c0cf16dbfe8a1d391a21bc81d8e3c89f268a64",
  "notes": "Pass-2 negatives recorded (VERDICT.md): xhci_init partial-failure self-cleans in usb_bus_mem_alloc_all (usb_controller.c:986-988) so the io_res-only unwind at xhci_pci.c:222 is correct; no DF-5509 analog (handler armed after offsets init, ACKs unconditionally at xhci.c:1654-1660); no MSI count math (pci_alloc_1intr fixed count=1); suspend/resume wired via usbus -> xhci_set_hw_power_sleep (xhci.c:4489); sc_vendor[16] ksprintf bounded; sc_io_size unused as bound; BIOS-handoff wait bounded 500x10ms. Known not re-reported: DF-1106, DF-2336 (extended-capability walk). Guest reset to with-src after the run.",
  "recommended_fix": "Check device_delete_children(self) at xhci_pci.c:355 and return the error before touching controller resources, so a child veto leaves IRQ/MMIO/DMA/softc fully intact and the caller retries later.",
  "fix_status": "fixed",
  "fix_baseline_reproduced": true,
  "fix_patched_reproduced": false,
  "fix_verdict": "fix.diff (check + propagate device_delete_children return) applied to guest /usr/src together with the DF-5546 fix in one quickkernel+installkernel rebuild; identical trigger returns 16 with refusing controller teardown, driver still bound, state DS_ATTACHED, DMA buffers unchanged, no panic on the cmd2 that killed the baseline; retry after the child cooperates completes a clean 0-children detach. Bad behavior gone.",
  "fix_evidence": "run.fix.log; fix_build.log (xhci_pci.c recompile + installkernel completed Wed Oct  7 09:43:48 UTC 2026)"
}