# DF-3486 VERDICT — REPRODUCED (panic, deterministic, root-only)

## Bottom line

Every creation of an `ng_eiface` node panics the stock kernel:
`panic: try holding ifnet lock in netisr` from `ifnet_lock()` ←
`if_attach()` ← `ether_ifattach_bpf()` ← `ng_eiface_constructor+0xf6`.
The constructors of the v1 netgraph interface nodes run in the netgraph
control-message path, which executes on a `TD_TYPE_NETISR` thread; `if_attach()`
is structurally forbidden there (ifnet lock KASSERT at sys/net/if.c:3787,
plus `netmsg_service_sync()` at if.c:741 which would self-deadlock).
`ng_iface` carries the same latent defect (ng_iface.c:605 `if_attach`,
ng_iface.c:801 `if_detach` in rmnode) — hidden on the stock kernel only
because DF-3485 panics earlier; demonstrated directly in
panic.iface_path.txt.

## How it was proven

1. Live reproduction, stock modules, fresh boot: `ngctl mkpeer . eiface e0
   ether` → instant panic; full trace captured first-hand (panic.txt).
   Deterministic on every attempt.
2. The DF-3482 lead's recorded message for this panic ("trying to free NULL
   pointer") was shown to be a truncation artifact: the actual console
   message and the two `ifnet_lock` frames were captured intact here.
3. Offsets resolved via module DWARF: `+0xf6` = return address of the
   `call ether_ifattach` at `+0xf1` (ng_eiface.c:356).
4. ng_iface variant reproduced with a DF-3485-only-fixed module (panic.
   iface_path.txt) — proving both files are affected and that
   `ng_iface_rmnode`'s if_detach is a further instance.
5. Fix validated (module rebuilds only): with fix.diff, both mkpeer
   triggers SUCCEED, `ng0`/`ngeth0` appear in ifconfig, `ngctl shutdown`
   is clean, and 22+ rapid create/destroy cycles (exercising
   PENDING/RUNNING/DONE/DYING/DETACHING transitions) produced zero panics;
   the guest stayed up (fix_run.log).

## Reachability / severity

Root-only (ng_socket.c:172 `caps_priv_check(SYSCAP_RESTRICTEDROOT)`; EPERM
verified for uid 1001). Impact: deterministic kernel panic — on INVARIANTS
kernels; on production kernels a netisr self-deadlock (hang) instead.
No memory corruption. Severity Low. These v1 modules are effectively
unusable crash-on-sight as shipped (they cannot have worked on any kernel
containing the ifnet_lock netisr assertion), i.e. this is long-standing
rot in the legacy v1 netgraph interface nodes, not a regression.

## Fix notes / residual

- The fix moves ifnet attach/detach into short-lived kernel threads with an
  ownership-transfer state machine (spinlock-protected). Validated for
  create / list / ifconfig / connect-hook / shutdown / rapid cycling.
- Not exercised by ngctl: `ng_eiface_rmnode`'s DONE-state path (ngctl's
  node-ID addressing did not resolve for the unnamed eiface node); that
  path is the unchanged original down-block, now merely gated on
  attach_state == DONE, and its state machine is identical in structure to
  ng_iface's validated one.
- Data through hooks racing an in-flight attach (rcvdata before if_attach
  completes) is a pre-existing semantic gap in these modules; the fix does
  not widen it (the node is hook-connectable only after the constructor
  returns, and ifnet fields are initialized before the thread starts).
- Upstream may prefer outright retirement of the v1 iface/eiface modules
  (netgraph7 provides equivalents); the fix demonstrates the defect is
  module-local and repairable.

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
