# DF-3758 VERDICT — `panic("tulip_rx_intr")` on RX DMA-map failure

## Status: `not_reproduced` (no de(4) hardware on the guest; panic path is
## compiled into the running kernel and source-certain)

## Root cause

```c
/* sys/dev/netif/de/if_de.c:3127-3150 (RX replenish loop) */
do {
    ...
    ms->m_len = ms->m_pkthdr.len = TULIP_RX_BUFLEN;
    error = bus_dmamap_load_mbuf(ri->ri_data_tag, *nextout->di_map, ms,
        tulip_dma_map_rxbuf, nextout->di_desc, BUS_DMA_NOWAIT);
    if (error) {
        device_printf(sc->tulip_dev,
            "unable to load rx map, error = %d\n", error);
        panic("tulip_rx_intr");          /* XXX */          <-- if_de.c:3139
    }
    ...
} while ((ms = me) != NULL);
```

The RX data tag is created with `BUS_SPACE_MAXADDR_32BIT`
(`if_de.c:3945-3947`), so on machines with memory above 4 GB every rx
cluster that lands high must bounce; `bus_dmamap_load_mbuf(..., BUS_DMA_NOWAIT)`
can then fail transiently (bounce-page pool exhausted / allocation failure
under memory pressure). The driver answers with an unconditional `panic()`
— the author even flagged it `/* XXX */`.

Compare the *correct* pattern 12 lines up: when `m_getcl()` fails
(`if_de.c:3114-3122`) the driver drops to `fillok = 0; TULIP_RXBUFSLOW;
continue;` and retries from the watchdog. The map-load failure deserves the
same treatment: free the mbuf chain, back off, retry later.

## Reachability

- Requires a machine with a de(4) NIC receiving traffic (any local user can
  generate RX by being sent packets / requesting traffic) plus enough
  memory/DMA-map pressure to make a NOWAIT map-load of a >4 GB cluster fail.
  Classic environmental-trigger local DoS; probability grows with RAM size,
  rx interrupt rate, and vm pressure.
- Audit guest: `de` is compiled into X86_64_GENERIC and the panic string is
  present in `/boot/kernel/kernel` (run.log: `strings` hits), but there are
  zero DEC 2114x PCI devices and zero `hw.de.*` OIDs — the path cannot
  execute. Hence `not_reproduced` / impact none *on this rig*.

## Evidence collected on the guest (run.log)

1. `strings /boot/kernel/kernel | grep tulip_rx_intr` → 3 hits — the panic
   is live in the running kernel binary.
2. `/usr/src/sys/dev/netif/de/if_de.c:3127-3145` excerpt — exact code.
3. `kldstat -v | grep pci/if_de` → 1 (driver compiled in);
   `sysctl -a | grep -c ^hw\.de\.` → 0 (never attached).

## Recommended fix

Drop the buffer and back off instead of panicking (fix.diff): free the
remaining chain, clear `fillok`, set `TULIP_RXBUFSLOW`, and break out of the
replenish loop — the watchdog (`if_de.c:3806-3807`) retries later, exactly
like the existing `m_getcl` failure path.

## Kernel references

- sys/dev/netif/de/if_de.c:3134-3140 (panic), 3106-3122 (correct degrade
  pattern for alloc failure), 3945-3947 (32-bit-limited RX data tag),
  3806-3807 (watchdog retry)

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