# DF-4305 VERDICT — sleepable allocation in bfe's interrupt-context reinit

## Bottom line

Source-certain defect; runtime not reproducible on this guest (no BCM4401;
QEMU cannot emulate one — env.txt). Recorded **not_reproduced** per family
convention (DF-3827). Impact ceiling on real hardware: interrupt-thread
stall / soft interface deadlock under cluster exhaustion — availability
only, Low severity, no corruption, no leak.

## Trace

1. `bfe_intr` (:1152-1200) processes `istat & BFE_ISTAT_ERRORS`
   (if_bfereg.h:40-41) → `bfe_init(sc)` at :1186 — this is the hardware
   interrupt handler (registered via `bus_setup_intr` :418-420, serializer
   passed).
2. `bfe_init` (:1355-1387) → `bfe_list_rx_init(sc)` :1368.
3. `bfe_list_rx_init` (:538-554) loops `bfe_newbuf(sc, i, 1)` — `init=1`.
4. `bfe_newbuf` (:557-595): `m = m_getcl(init ? M_WAITOK : M_NOWAIT,
   MT_DATA, M_PKTHDR)` :565 — **M_WAITOK in ithread context**.
5. On `bus_dmamap_load_mbuf_segment` failure: `if_printf` :576 (console
   output from interrupt context — tolerated but noisy).

Sibling path: `bfe_watchdog` :1470-1483 → `bfe_init` :1480 runs from
`if_slowtimo_dispatch` (netisr, sys/net/if.c:1900-1912) — also
non-sleepable.

## Why it matters (threat)

`BFE_ISTAT_RDU` (receive descriptor underflow) is raised when the driver
runs out of posted RX buffers — i.e. under cluster shortage. The recovery
path then demands 511 new clusters with M_WAITOK from the ithread. Under
the same shortage the allocator sleeps; the ithread (holding the
serializer, pinning its IRQ) sleeps with it. Until clusters free up
(possible only if other CPUs/network progress releases them) the NIC and
its interrupt line are dead; if nothing frees clusters (all freeing paths
blocked behind the same serializer), the stall is permanent. Realistic but
narrow: Low severity.

## Negative results (adjacent, this file)

- `bfe_init` from `bfe_ioctl` (SIOCSIFFLAGS :1448) is process context —
  M_WAITOK fine there.
- `bfe_list_rx_init` error path (`== ENOBUFS` :1368-1373) stops and calls
  `bfe_stop` — clean.
- The map-swap in `bfe_newbuf` (:583-588) is correct on both load-success
  and retained-mbuf paths.

## Fix validation

fix.diff plumbs `waitok` (intr/watchdog pass 0 → M_NOWAIT; process paths
keep M_WAITOK), `patch -p1 --dry-run` clean. Cannot be runtime-validated
without hardware → fix_status not_testable.

## 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.
