# DF-5299 evidence pack — usb_device.c pass-2

## What this pack contains

1. **The finding DF-5299** (`usbd_get_phys()` unchecked `pci_devinfo *` type
   confusion / NULL parent deref) — **source-verified only**: the trigger
   requires a USB host controller whose newbus parent is NOT a PCI device
   (or has no ivars). On the x86-64 QEMU target every USB HCI (xhci, ehci)
   is a PCI child, so the faulty branch cannot be entered at runtime here.
   That is an architectural limit of the test target, not a refutation.

2. **A file-level stress soak of `sys/bus/u4b/usb_device.c`** (usbsoak.c) —
   the primary artifact of this pack. It hammers every ugen-reachable entry
   point into the audited file with hostile-but-legal values while USB
   devices are replugged underneath, to give the pass-2 **negative result**
   (no new memory-safety defect beyond DF-1003/1004/1005) runtime weight.

## Build (on the guest, as root)

    cc -O2 -pthread -o usbsoak usbsoak.c

## Run (as root on the guest)

    # guest booted with USB devices, e.g. QEMU:
    #   -device qemu-xhci,id=xhci0 \
    #   -device usb-ehci,id=ehci0 \
    #   -drive if=none,id=usb0,file=usbstick.img,format=raw \
    #   -device usb-storage,bus=ehci0.0,drive=usb0 \
    #   -device usb-tablet,bus=ehci0.0,port=2,id=tab0
    ./usbsoak 424242            # ~90 s, two devices + reopener thread
    # concurrently, from the QEMU monitor:
    #   device_del tab0 ; device_add usb-tablet,bus=ehci0.0,port=2,id=tab0
    #   (48 total cycles, 18 slow ~2.4 s + 30 fast)

## Expected output (observed)

    soak done: ops=70139 alt_ok=56 cfg_ok=939 (errors expected, panic = FAIL)
    soak done: ops=68914 alt_ok=34 cfg_ok=620 (errors expected, panic = FAIL)

* **139,053 hostile ioctls** across USB_SET_ALTINTERFACE (iface/alt values
  including 31/255 + random), USB_SET_CONFIG (0/1/2/255/random),
  USB_GET_FULL_DESC (random config index/offset/len), USB_DO_REQUEST,
  USB_IFACE_DRIVER_DETACH.
* 1,559 successful set_config cycles = 1,559 full
  `usb_unconfigure` → `usb_config_parse(ALLOC|INIT|FREE)` → `usb_cdev_create`
  round-trips, concurrent with open/ioctl on the same device.
* 90 successful alt changes plus tens of thousands of IN_USE/EINVAL rejections
  through the `usb_config_parse()` zeroing loop.
* 48 device replug cycles concurrent with the above (usb_free_device /
  usb_alloc_device / async cdev destroy churn, device-index reuse window).

**Result: no panic, no devfs corruption warnings, guest stayed up and
consistent after both runs.** The `usb_device.c` state machine survived
everything thrown at it.

## Guest

    DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026
    (X86_64_GENERIC), QEMU/KVM, qemu-xhci + usb-ehci + usb-storage + usb-tablet

DF-5299 itself: **inconclusive at runtime** — trigger needs non-PCI USB HCI
(absent on x86); see VERDICT.md.
