DF-5268 / verdict.json
{ "finding_id": "DF-5268", "status": "reproduced", "verdict": "xhci_init() latches CAPLENGTH/RTSOFF/DBOFF register offsets verbatim from controller MMIO (xhci.c:626-629) with no bounds check against the mapped BAR size; all XREAD/XWRITE macros (xhcireg.h:205-222) then use them raw. A malicious controller returning DBOFF=0xF0000000 makes the very next doorbell write an OOB MMIO write ~3.75GB past the 16KB BAR. Verified on QEMU/KVM DragonFly 6.5-DEVELOPMENT: latching simulation of the malicious register value + ordinary USB device insertion (ENABLE_SLOT command) yields Fatal trap 12: supervisor write data, page not present at xhci_do_command+0x216 (movl $0,(%rdx)) with fault VA exactly io_hdl+0xF0000000. fix.diff (init-time validation + runtime doorbell guards) rebuilt and re-tested: identical trigger produces no panic, graceful enumeration failure, guest survives 4 plug/unplug cycles with the poison still loaded. Impact ceiling: device-directed OOB MMIO read/write (panic proven; adjacent-register corruption possible), attacker class is malicious/compromised PCIe-attached xHCI hardware (AV:P).", "reproduced": true, "impact": "panic", "confidence": "certain", "exploit_chain": "malicious xHCI controller (Thunderbolt/PCIe hotplug or emulated) returns DBOFF=0xF0000000 in capability registers -> xhci_init latches it unchecked -> any USB device insertion triggers ENABLE_SLOT -> xhci_do_command XWRITE4(sc,door,XHCI_DOORBELL(0),0) writes to io_hdl+0xF0000000 -> kernel page fault panic (proven); with an offset that lands on adjacent mapped MMIO -> cross-device register corruption instead (bounded by hardware topology)", "evidence": "panic.txt (fault VA 0xfffff8017df7b000 = io_hdl 0xfffff8008df7b000 + 0xF0000000, supervisor WRITE); run.log (baseline panic + fixed-kernel survival); poison.c (latch simulation module); fix.diff + fix_build_guest.log (validated fix)", "kernel_refs": [ "sys/bus/u4b/controller/xhci.c:626-629", "sys/bus/u4b/controller/xhcireg.h:205-222", "sys/bus/u4b/controller/xhci_pci.c:204-213", "sys/bus/u4b/controller/xhci.c:1235", "sys/bus/u4b/controller/xhci.c:1653", "sys/bus/u4b/controller/xhci.c:2855-2872" ], "poc_changes": "Authored the PoC from scratch (no seed). KLD module walks devclass xhci -> softc and writes the malicious DBOFF value into the already-latched sc_door_off, which is bit-identical to what xhci_init() would have stored from that register; trigger is a genuine USB device insertion via QEMU monitor.", "attempts": 3, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0/#1 x86_64 (QEMU/KVM, qemu-xhci 1b36:000d)", "runtime_sec": 1450, "guest_dirty": 1, "build_cmd": "cd /root/xhcipwn && make KERNBUILDDIR=/usr/obj/usr/src/sys/X86_64_GENERIC", "run_cmd": "kldload /root/xhcipwn/xhcipwn.ko ; QEMU monitor: device_add usb-mouse,id=m1,bus=xhci0.0,port=3", "code_hash": "908968a71cab7c572a58a3922c187c1e89387f0d420985a7695102188003dee0", "notes": "QEMUs own xhci hardcodes sane offsets, so the malicious register value was injected as the latched copy via KLD (documented in VERDICT.md); everything downstream is the drivers unmodified code. Guest reset to clean-source snapshot after validation. Kin of DF-1106/DF-2336 (XECP walk in xhci_pci.c) but a distinct defect in xhci.c affecting every register access.", "recommended_fix": "Validate CAPLENGTH/RTSOFF/DBOFF against sc_io_size in xhci_init() (ENXIO on violation) and bounds-check doorbell writes at use (fix.diff)", "fix_status": "fixed", "fix_baseline_reproduced": true, "fix_patched_reproduced": false, "fix_verdict": "Baseline kernel: deterministic panic (Fatal trap 12, supervisor write) on trigger. Kernel+fix.diff (nativekernel build #1): identical trigger produces no panic, no fault; enumeration fails gracefully; guest survived 4 additional plug/unplug cycles with the poisoned offset still installed. Bad behavior eliminated.", "fix_evidence": "run.log (both phases); fix_build_guest.log; panic.txt vs post-fix dmesg grep -c Fatal trap = 0" } |