# DF-5533 — usb_proc_drain() cold-path: unconditional suspend_kproc() hang

File: `sys/bus/u4b/usb_process.c` (pass 2)

## What this demonstrates

`usb_proc_drain()`'s cold-boot branch (usb_process.c:433-439):

```c
if (cold) {
        USB_THREAD_SUSPEND(up->up_ptr);   /* suspend_kproc(p, 0) */
        kprintf("WARNING: A USB process has been left suspended\n");
        break;
}
```

calls `suspend_kproc()` (sys/kern/kern_kthread.c:188-204), which
**tsleeps until the target thread acknowledges** TDF_MP_STOPREQ — but
`usb_process()` never runs any suspend check: the intended
`USB_THREAD_SUSPEND_CHECK()` at usb_process.c:86-89 is `#if 0`'d out,
and the macro it expands to (`kthread_suspend_check(curproc)`,
usb_process.c:60) **does not exist anywhere in the DragonFly kernel**
(the real primitive is `kproc_suspend_loop()`, used by bufdaemon/
syncer/vfs_mount). The drain thread therefore sleeps forever in
"suskp" **while holding the USB bus lock**, and the USB process thread
can never acquire the lock to exit either → permanent double-wedge.

Reachability: `cold` is true during autoconfiguration; a USB
controller attach failure reaching `usb_proc_free()`/`usb_proc_drain()`
(sys/bus/u4b/controller/usb_controller.c:210-236, 879-900 error path)
during boot wedges the boot with the bus lock held. Not attacker-
reachable in the standard configuration — this is a hardware/
hypervisor-triggered boot DoS (Low).

## Build / run (on the QEMU guest, as root)

Same harness as DF-5532 (`dfharness.c`):

```
cd /root/dfharness && make && kldload ./dfharness.ko
sleep 1; sysctl kern.dfstarv.stop=1      # quiesce the churn demo
sleep 2
nohup sh -c 'sysctl kern.dfcold.fire=1; echo rc=$?' > /root/fire.log 2>&1 &
sleep 3;  cat /root/fire.log            # EMPTY: never returned
ps -axH -o pid,stat,wchan,comm | grep -E 'dfhz|sysctl'
# -> sysctl thread in D-state, wchan "suspkp"; no WARNING printed
```

## Expected (baseline, unpatched kernel)

```
1028  D1  suspkp  sysctl      # uninterruptible, forever
fire.log empty (no return, and usb_process.c:437's WARNING never prints)
```

## Fix

`fix.diff` (shared with DF-5532; validated in the same patched-kernel
build): (1) loop-top `USB_THREAD_SUSPEND_CHECK()` → `kproc_suspend_loop()`
(the existing DF daemon idiom), (2) release the bus lock around
`suspend_kproc()` so the target can actually run its suspend check.
