# Fix validation - DF-5308

## Baseline (unpatched with-src kernel, `usb_dev.c` md5 8307905e7ec38912ff7e2883279a187b
## == audited tree)

| rig | result |
|---|---|
| `./df5308 fault 2` (kn_fop=0x4141414141414141) | **panic x3**: `Fatal trap 9 ... Stopped at filter_event+0x4: testb $0x2,(%rax)` (panic.txt, panic.2.txt, panic.fault.txt) |
| `DF5308_FOP=<kprintf-24> ./df5308 call` (kn_fop=&kprintf-24) | **trap x2**: `Stopped at filter_event+0x1d: ret` (panic.call.txt, panic.call.1.txt) |
| markers | saturated: `ioctl = -1 ENXIO`; drained: `ENOTTY` - the exact `usb_ref_device()` failure path `usb_filter_detach` hits |

## Patched kernel (fix.diff: `usb_filter_detach_unlink()` on the error path)

Build: `cd /usr/src && make -j 6 nativekernel KERNCONF=X86_64_GENERIC` ->
BUILD_RC=0; `make installkernel` -> INSTALL_RC=0; kernel
`#1: Fri Oct 2 13:50:14 UTC 2026`.

| check | result |
|---|---|
| `./df5308 fault 2` (identical rig) | **no crash**: both attempts run the full choreography (saturation ENXIO marker present -> the failing `usb_ref_device` path is exercised), `close(fd)` returns, process exits 0 (run.patched.log) |
| guest stability | `vm.sh status: up`, serial log clean, no wedge, no delayed trap |
| kqueue subsystem sanity | 96+64 knote register/drop cycles per attempt complete without error |

The fix removes the knote from the fifo klist on the error path, so the
`KNOTE()` walk at `usb_fifo_close()` no longer visits freed memory; the
`usb_ref_device()` failure itself (saturation) still occurs exactly as
before, isolating the fix to the dangling-link consequence.
