# DF-5359 — uipaq attach-time USB-explore-thread stall (64 × (100ms + 100ms))

**File:** `sys/bus/u4b/serial/uipaq.c:1129-1136`
**Severity:** Low (crafted-USB-device, bounded multi-second DoS of USB enumeration)
**PoC status:** untested — see VERDICT.md for why this is honestly untestable on
the project's QEMU rig (no QEMU USB device model can present a uipaq-table
VID:PID; QEMU 7.2 exposes no vendorid/productid override for usb-net or
usb-storage, and the attachable usb-serial device is 0525:7701 which binds
`uftdi`, not `uipaq`).

## What the bug is

`uipaq_attach()` sends a "magic" `UCDC_SET_CONTROL_LINE_STATE` control request
up to 64 times before setting up transfers and attaching the ucom:

```c
for (i = 0; i != 64; i++) {
        error = usbd_do_request_flags(uaa->device, NULL, &req,
            NULL, 0, NULL, 100);            /* 100 ms request timeout */
        if (error == 0)
                break;
        usb_pause_mtx(NULL, hz / 10);       /* ~100 ms pause, unconditional */
}
```

* Device present but NAK-ing the request (crafted gadget, or wedged HW):
  64 × (100 ms timeout + ~100 ms pause) ≈ **12.8 s**.
* Device that STALLs the request or is already gone (yanked mid-attach):
  requests fail fast but the pause still runs 64 × ~100 ms ≈ **6.4–7 s**.

This loop runs inside `usb_probe_and_attach()` (sys/bus/u4b/usb_device.c:1286,
called from `uhub_explore_sub()`), i.e. on the kernel USB explore thread that
serially handles **all** hub events for the bus, while holding the device's
enum lock (`usbd_enum_lock`, usb_device.c:1324). One crafted device therefore
delays enumeration/detach of every other device on that bus for up to ~13 s
per insertion, repeatably (replug).

## How a human could reproduce it (needs real HW, not QEMU)

1. Take a scriptable USB device (e.g. Facedancer21/USBProxy, or a gadget-mode
   dev board) and present VID:PID from `uipaq_devs[]` — e.g.
   `0x049f:0x0032` (Compaq iPAQ USB Sync, uipaq.c:300).
2. Configure its EP0 to NAK (or STALL) the `SET_CONTROL_LINE_STATE`
   class-interface request (bmRequestType 0x21, bRequest 0x22).
3. Plug it into a DragonFly host (uipaq.ko auto-loads — the module is built
   and installed: sys/bus/u4b/serial/uipaq/Makefile; /boot/kernel/uipaq.ko
   exists on the audit guest).
4. Expected: ~6–13 s gap on the serial console between the uhub attach line
   and `uipaq0` attach/transfer-setup messages; hotplug events for other
   devices on the same bus are delayed by the same amount.

## Fix

See `fix.diff` — retry only while the request merely times out (the real
"WinCE device warming up" case), give up immediately on stall/gone, and cap
the retry count so the worst case is ~3 s instead of ~13 s.

Upstream note: FreeBSD `sys/dev/usb/serial/uipaq.c` carries the identical
loop (inherited from OpenBSD/NetBSD) — coordinate the fix upstream.
