# DF-5397 — urndis(4) attach-failure paths call urndis_detach() on a
# never-attached usb_ether -> deterministic kernel panic (lockmgr NULL)

## What

`sys/bus/u4b/net/if_urndis.c` — `urndis_attach()` failure paths
(if_urndis.c:258-299: "No valid alternate setting found", "Unable to
get hardware address", "Invalid address length", "Unable to set data
filters") jump to:

```c
detach:
	urndis_detach(dev);          /* if_urndis.c:309-311 */
	return (ENXIO);
```

`ue->ue_lock`, `ue->ue_methods` etc. are assigned only at
if_urndis.c:290-294 — *after* every failure goto — and
`uether_ifattach()` never ran. `urndis_detach()` calls
`uether_ifdetach(ue)`; on DragonFly every guard there is dead:

* `usb_proc_drain()` early-returns (zeroed `up_lock`) — safe;
* `uether_getifp(ue)` returns the address of the **embedded**
  `ue->ue_arpcom.ac_if` — never NULL — so `if (ifp != NULL)` passes;
* `UE_LOCK(ue)` → `lockmgr(ue->ue_lock == NULL)` → **page fault VA 0**.

Identical class to DF-5334 (cdce). An attacker-supplied USB device
(evil RNDIS NIC / tethering dongle — precisely this driver's threat
model) triggers it by making the attach fail once: e.g. malformed
class-specific descriptors so `usbd_transfer_setup()` finds no usable
alternate setting on the data interface (the exact gadget used here),
or by failing/short-answering the RNDIS MAC query.

## Reproduction (baseline, stock if_urndis.ko)

Malformed RNDIS gadget over usb-redir (`RNDIS_MALFORMED=1
boot_rig_cold.sh`, `usbredir_rndis.py` with `malformed on`):

```
urndis0: <vendor 0x0525 product 0xa4a2, class 2/0, rev 2.00/0.00, addr 2> on usbus0
urndis0: No valid alternate setting found
Fatal trap 12: page fault while in kernel mode
fault virtual address	= 0x0
Stopped at      lockmgr_exclusive+0x5d: orl     (%r14),%esi

lockmgr_exclusive() at lockmgr_exclusive+0x5d
uether_ifdetach() at uether_ifdetach+0x2f
urndis_detach() at urndis_detach+0x2a
urndis_attach() at urndis_attach+0x11d
device_doattach() at device_doattach+0x3af
usb_probe_and_attach() at usb_probe_and_attach+0x176
uhub_explore() at uhub_explore+0x231
usb_bus_explore() at usb_bus_explore+0xd0
usb_process() at usb_process+0x76
```

(4 independent reproductions; crash dump taken via `call dumpsys`.
A second variant — "Unable to get hardware address" when the RNDIS
query response is rejected — panics at urndis_attach+0x13a with the
same teardown, captured in run.serial-baseline-panic-usbdebug.log.)

## Fix validation (patched if_urndis.ko, fix.diff)

`fix.diff` replaces the error-path `urndis_detach(dev)` with a teardown
of only what was actually initialised (USB transfers + the softc lock).
Same malformed device, patched module:

```
urndis0: <vendor 0x0525 product 0xa4a2, class 2/0, rev 2.00/0.00, addr 2> on usbus0
urndis0: No valid alternate setting found
device_probe_and_attach: urndis0 attach returned 6
```

Guest stays up (ssh alive, zero `Fatal trap` in dmesg.boot), attach
retried cleanly, and the unpatched flow of DF-5396 (valid device)
still attaches (`ue0: MAC address: 02:00:de:ad:be:ef`) — no regression.

## Run it

1. guest: `mv /boot/kernel/if_cdce.ko /root/` (cdce's VPI match on
   0525:a4a2 would win probe priority and panic via its own DF-5334
   bug first), `kldload if_urndis`
2. host: `RNDIS_MALFORMED=1 sh boot_rig_cold.sh` (device present at
   boot, malformed CS descriptors) — or toggle `malformed on` on the
   control port and replug.
3. baseline: panic (above); patched: clean ENXIO, guest survives.

## Kernel references

- sys/bus/u4b/net/if_urndis.c:290-294 (ue fields assigned after all
  failure gotos), :309-311 (goto detach -> urndis_detach)
- sys/bus/u4b/net/usb_ethernet.c:268-314 (uether_ifdetach),
  :54-56 (URNDIS/UE lock macros), sys/bus/u4b/usb_process.c (drain
  guard)
- sibling finding DF-5334 (cdce, same class)
