# DF-4304 — bfe_rxeof/bfe_txeof walks trust the 12-bit DMA "current descriptor" field with no range validation and no work bound: an encodable off-ring index (511) makes the interrupt loop non-terminating (serializer-held livelock)

**File:** `sys/dev/netif/bfe/if_bfe.c` (pass 2; known DF-1509 not touched)
**Lines:** 1059-1093 (`bfe_txeof`: `chipidx` decode :1064-1065, unbounded walk :1070-1083, `KKASSERT(tx_cnt>0)` :1080), 1097-1150 (`bfe_rxeof`: `current` decode :1106-1107, unbounded walk :1109-1147)
**Registers:** `sys/dev/netif/bfe/if_bfereg.h:69` `BFE_STAT_CDMASK 0x00000fff` (12-bit byte offset), `:405-406` ring counts 511, `:434-437` `struct bfe_desc` = 8 bytes, `:426` `BFE_INC` wraps 0..510.

## The bug

Both completion walks decode the hardware's "current descriptor" byte
offset from DMARX_STAT/DMATX_STAT and use it directly as the loop's
termination target:

```c
bfe_txeof:  chipidx = (CSR_READ_4(sc, BFE_DMATX_STAT) & 0xfff) / 8;  /* :1064 */
            while (i != chipidx) { ...; BFE_INC(i, 511); }           /* :1070 */
bfe_rxeof:  current = (CSR_READ_4(sc, BFE_DMARX_STAT) & 0xfff) / 8;  /* :1106 */
            while (current != cons) { ...; BFE_INC(cons, 511); }     /* :1109 */
```

The 12-bit field encodes byte offsets 0..4095 → descriptor indices 0..511,
but the ring holds **511** descriptors (valid indices 0..510; EOT at 510).
Software indices cycle over 0..510 via `BFE_INC` and can **never** equal
511. Any hardware-reported offset in **[4088..4095]** — i.e. index 511 —
therefore makes the loop non-terminating:

- `bfe_rxeof` spins forever in **interrupt context holding the serializer**:
  every iteration allocates a fresh cluster (`bfe_newbuf`), loads a DMA
  map, reads a zeroed header (`len=0 - 4` underflows → error branch), and
  bumps ierrors — an mbuf-alloc storm at full interrupt priority.
- `bfe_txeof` spins the same way freeing nothing; if the phantom walk
  crosses an empty ring it first trips `KKASSERT(sc->bfe_tx_cnt > 0)`
  (:1080) → panic instead.

There is no range check on the decoded index and no iteration bound.

The off-ring encoding is **architecturally used on this very register
interface**: the driver itself programs `511 * 8 = 4088` into BFE_DMARX_PTR
at if_bfe.c:549 (`bfe_list_rx_init` writes `i * sizeof(struct bfe_desc)`
after the loop, i == 511). Nominal DMARX_STAT values stay ≤ 4087 because
the EOT descriptor at 510 wraps the engine, but any transient (post-EOT
increment-before-wrap), error state, or bit-flip that reports 4088..4095
converts the next RX/TX interrupt into an unkillable livelock. The RX/TX
error interrupts (`BFE_ISTAT_RDU` etc.) that typically accompany such
states are handled by `bfe_init` re-init **before** `bfe_rxeof` runs
(:1176-1191), so the error path does not clean the wedged state.

Secondary aspect (DF-3761 family): even for in-range values the walks have
**no work bound** — no `process_limit`-style cap like FreeBSD's alc/msk or
DFly msk(4) — so a sustained small-frame flood keeps the walk perpetually
non-empty within a single interrupt.

## Proven (index-space + loop-termination harness, guest)

```
bfe walk harness: CDMASK=0xfff desc_sz=8 ring=511 entries (valid 0..510)
encodable descriptor indices: 0..511  -> index 511 is OUTSIDE the ring (ring max 510)
offsets encoding the off-ring index: [4088..4095]  (driver itself writes 4088 (511*8) to BFE_DMARX_PTR at if_bfe.c:549)
current=511: walk NEVER TERMINATES (no cons in 0..510 equals it; >1e6 steps)
RESULT: off-ring index 511 => bfe_rxeof/bfe_txeof walk cannot terminate (interrupt-context livelock holding the serializer)
```

The guest has **no Broadcom PCI device** (`NO_BROADCOM_PCI`, `hw.bfe`
unknown oid) and QEMU provides no BCM4401 model, so the driver itself
cannot be executed — per family convention (DF-3761/DF-3715) recorded as
**inconclusive**; the invariant break is certain from source + harness.

## Build/run (guest)

```
cc -o /root/bfe_walk_harness /root/bfe_walk_harness.c   # build.log
/root/bfe_walk_harness                                  # run.log
```
