DF-5562 / verdict.json
{ "finding_id": "DF-5562", "status": "reproduced", "reproduced": true, "impact": "panic", "confidence": "certain", "verdict": "ohci_pci_detach() discards device_delete_children()s return at sys/bus/u4b/controller/ohci_pci.c:329 and unconditionally disables bus mastering, resets the controller via ohci_detach() (:337), tears down and releases the IRQ (:339-351), releases the MMIO BAR (:352-356), frees all USB DMA via usb_bus_mem_free_all() (:357) and returns 0 (:359). Demonstrated live on the QEMU guest with a real OHCI controller (-device pci-ohci, Apple KeyLargo 0x003f106b, ohci compiled into X86_64_GENERIC): with one child vetoing detach, device_detach(ohci0) reported complete success (ohci0: detached, returned 0), left the vetoing child ATTACHED to the now-driverless ohci0 whose softc had been kfreed/NULLed by device_set_driver(dev,NULL) (subr_bus.c:2150 -> 1943-1945) -- the next touch of the parent context through the orphan was a Fatal trap 12 page fault (NULL softc + 0x58 field offset = offsetof(ohci_softc, sc_hw.hcca_pc.buffer), Stopped at df5562_thread+0x91 movq 0x58(%rax),%rcx), guest dead in DDB with the ssh session frozen mid-command. 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:189-241) -- exact OHCI family recurrence of DF-5544 (uhci, proven identically this pass), DF-5545 (xhci, 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 (quickkernel+installkernel Wed Oct 7 18:32:42 UTC 2026, kernel #1 18:31:30): identical trigger now returns 16 with child device failed to detach (16); refusing controller teardown, driver still bound (state=3 DS_ATTACHED), HCCA/ctrl-ED 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 returning 0.", "exploit_chain": "privileged: kldunload ohci / PCI hot-unplug -> devclass_delete_driver (subr_bus.c:889-897) -> device_detach(ohci0) -> ohci_pci_detach -> device_delete_children fails (child veto at subr_bus.c:1284-1292) -> return value discarded at ohci_pci.c:329 -> ohci_detach() halts/resets the HC, IRQ torn down + released, MMIO BAR released, usb_bus_mem_free_all frees HCCA/ED/TD DMA pages, returns 0 -> device_set_driver(NULL) kfrees softc, device_get_softc(ohci0) becomes NULL -> still-attached child operates on freed/NULL parent state -> supervisor page fault (observed, fault va 0x58) / UAF reads of freed DMA pages (harness cmd3). Not reachable by an unprivileged user through this file.", "evidence": "panic.txt (raw serial: veto -> ohci0: detached -> returned 0 -> veto0(attached=1) -> Fatal trap 12 fault va=0x58, Stopped at df5562_thread+0x91 movq 0x58(%rax),%rcx, db>); run.log (baseline transcript + root-cause chain); run.fix.log (patched kernel: R1 child device failed to detach (16); refusing controller teardown, returned 16, driver=ohci state=3, hcca/ctrl-ED buffers unchanged, guest alive through the killing touch; R2 cooperative retry -> clean 0-children detach); veto.c/Makefile/build.sh/run.sh (harness); build.log; fix_build.log (quickkernel+installkernel completed Wed Oct 7 18:32:42 UTC 2026); env.txt; fix.diff (git-apply --check verified)", "kernel_refs": [ "sys/bus/u4b/controller/ohci_pci.c:329", "sys/bus/u4b/controller/ohci_pci.c:331", "sys/bus/u4b/controller/ohci_pci.c:337", "sys/bus/u4b/controller/ohci_pci.c:348", "sys/bus/u4b/controller/ohci_pci.c:352", "sys/bus/u4b/controller/ohci_pci.c:357", "sys/bus/u4b/controller/ohci_pci.c:359", "sys/kern/subr_bus.c:1284", "sys/kern/subr_bus.c:1326", "sys/kern/subr_bus.c:2129", "sys/kern/subr_bus.c:2150", "sys/kern/subr_bus.c:1943", "sys/kern/subr_bus.c:889", "sys/bus/u4b/controller/usb_controller.c:189", "sys/bus/u4b/controller/ohci.c:430" ], "poc_changes": "Adapted the proven DF-5544 uhci harness to ohci (DRIVER_MODULE(veto, ohci, ...), devclass_find(\"ohci\"), snapshot of sc_hw.hcca_pc / sc_hw.ctrl_start_pc DMA pages instead of the uhci frame list, sysctl hw.df5562). Guest booted with QEMU_EXTRA=-device pci-ohci (Apple KeyLargo OHCI at pci0:0:3:0); ohci 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.df5562=2 exactly as predicted (fault va 0x58 = NULL softc + offsetof(sc_hw.hcca_pc.buffer)); fix validated on a quickkernel-rebuilt guest with the same rig.", "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 #1: Wed Oct 7 18:31:30 UTC 2026, quickkernel+installkernel completed 18:32:42 UTC 2026)", "runtime_sec": 1380, "guest_dirty": 0, "build_cmd": "cd /root/df5562 && make KERNBUILDDIR=/usr/obj/usr/src/sys/X86_64_GENERIC", "run_cmd": "kldload /root/df5562/veto.ko; sysctl hw.df5562=1; sysctl hw.df5562=2", "code_hash": "67a1166d402074dc3b949c6ef6b103337ff725c594e6e72fd8d4afca34d8da63", "notes": "Pass-2 negatives (VERDICT.md): NO DF-5546 MSI analog -- ohci_pci never calls pci_alloc_1intr/pci_alloc_msi, IRQ is plain shareable INTx rid=0 (:240-242) released with matching rid (:348-351), nothing to leak; attach-unwind sound -- ohci_init CAN fail (ohci.c:424-425, unlike uhci_init) but the :333 gate is safe because sc_tmo_rhsc is callout-initd at ohci.c:401 before ohci_controller_init at :424 and MMIO is still mapped, usb_attach returns 0 unconditionally (usb_controller.c:163-182), usb_bus_mem_alloc_all self-cleans; suspend/resume are bare bus_generic pass-through (:367-368, functional gap only); sc_vendor[16] ksprintf bounded (:259-297, ohci.h:253); sc_io_size BAR size consumed only by ohci.c (its own row); SMM/BIOS handoff (:92-109) and Sun intpin quirk (:226-227) benign; return-0-despite-teardown_intr-failure (:339-345 XXX or should we panic?) folded into this findings check-and-propagate fix. Guest reset to with-src after the run.", "recommended_fix": "Check device_delete_children(self) at ohci_pci.c:329 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, quickkernel+installkernel rebuild (completed Wed Oct 7 18:32:42 UTC 2026), reboot with the same -device pci-ohci and the same harness: identical trigger returns 16 with child device failed to detach (16); refusing controller teardown, driver still bound (driver=ohci state=3), HCCA/ctrl-ED DMA buffers byte-identical, no panic on the hw.df5562=2 touch that killed the baseline; retry after the child cooperates completes a clean 0-children detach returning 0. Bad behavior gone.", "fix_evidence": "run.fix.log; fix_build.log (quickkernel + installkernel for X86_64_GENERIC completed Wed Oct 7 18:32:42 UTC 2026)" } |