# DF-5384 — if_aue.c attach-failure DF-5334-class panic (goto-detach-on-unattached)

## What

`aue_attach()` (`sys/bus/u4b/net/if_aue.c`) routes its device-controlled
failure branch through `aue_detach()` on a `usb_ether` that was never
attached — identical class to DF-5334 (`if_cdce.c`, proved on this guest):

- `usbd_transfer_setup()` fails (missing bulk/interrupt endpoints on an
  otherwise matching Pegasus device) → `if_aue.c:689-691` `goto detach` →
  `if_aue.c:707-708` `aue_detach(dev)`.
- At that point `ue->ue_lock`, `ue_dev`, `ue_udev`, `ue_methods`, `ue_tq`
  are ALL still zero — they are assigned only at `if_aue.c:694-698`,
  *after* the failing call.
- `aue_detach()` (`if_aue.c:719`) calls `uether_ifdetach(ue)`
  (`usb_ethernet.c:267-305`): `usb_proc_drain()` is a no-op on the zeroed
  `ue_tq`; `uether_getifp()` returns the embedded arpcom ifnet (never
  NULL — the `if (ifp != NULL)` guard is dead code); then
  `usb_ethernet.c:281` `UE_LOCK(ue)` = `lockmgr(NULL, LK_EXCLUSIVE)`
  → **Fatal trap 12, fault VA 0x0**.

The second failure branch (`uether_ifattach()` error, `if_aue.c:700-704`)
has the same shape and additionally reaches `ether_ifdetach()` on a
never-`if_attach()`ed ifnet → `ifindex2ifnet[0]` nulling + global ifnet
list corruption (requires `usb_proc_create()` ENOMEM — not
attacker-timed).

Threat model: attacker-supplied USB device (evil adapter / evil dock /
VM attach) presenting any of the 68 VID:PID pairs in `aue_devs[]`
(e.g. ADMtek Pegasus `0x077b:0x2226`) at config 0 / iface 0 **without**
the expected bulk-in/out + interrupt-in endpoints. Not remotely
triggerable, not an unprivileged-local program — physical/VM USB access.

## Reproduce (evidence class: KLD harness driving production code)

QEMU cannot emulate a Pegasus AN986. The harness `aue_attach_poc.c`
replays `aue_detach()` **verbatim** (its two production calls, in order)
on the exact state `aue_attach()`'s failure branch produces, using the
**production** `usbd_transfer_unsetup()` and `uether_ifdetach()` (exported
by `uether.ko`). The only non-production code is the static
`aue_attach`/`aue_detach` frame itself (they are `static` in `if_aue.c`
and only reachable via `goto detach` with a physical device present).

```sh
# build (in guest, source pack synced to /root/df5384)
cd /root/df5384 && make -m /usr/src/share/mk

# run (auto-loads STOCK /boot/kernel/uether.ko as dependency)
kldload -v ./aue_poc.ko
# expected: 3 marker lines, then
#   Fatal trap 12: page fault while in kernel mode
#   fault virtual address = 0x0
#   Stopped at lockmgr_exclusive+0x5d: orl (%r14),%esi
#   (guest dead in DDB)
```

## Fix validation

`fix.diff` (git-apply-able against clean `sys/`): (a) class-wide guard in
`uether_ifdetach()` — early return when `ue->ue_lock == NULL` (same fix
already validated for DF-5334); (b) `aue_attach()` routes both
pre-attach failure branches to a local `detach_usb:` label doing only
`usbd_transfer_unsetup()` + `lockuninit()` (fixes the branch-2
`ether_ifdetach`-on-unattached corruption too).

Applied to the guest's `/usr/src`, both modules rebuilt `-Werror` clean,
patched `uether.ko` installed: identical harness run prints
`aue_poc: SURVIVED uether_ifdetach()`, `KLDLOAD_RC=0`,
`dmesg | grep -c 'Fatal trap'` = 0, clean `kldunload`, patched
`if_aue.ko` driver loads/unloads clean. See `run.log` vs `panic.txt`.

## Files

- `aue_attach_poc.c` + `Makefile` — the harness
- `build.log` — harness build (full, -Werror)
- `fix_uether_build.log` / `fix_if_aue_build.log` — patched module builds
- `panic.txt` — baseline serial record (stock modules)
- `run.log` — patched run (survival proof)
- `env.txt` — guest uname, dmesg tail, kldstat
- `fix.diff` — the fix (never applied to the audit tree)
- `VERDICT.md`, `manifest.json`, `verdict.json`
