/*
 * DF-3663 — bge(4) RX path trusts NIC-DMA'd return-ring bge_len
 *
 * Trigger (HARDWARE REQUIRED — cannot run on the audit guest):
 *
 *   The BCM57xx (bge) RX completion path processes `struct bge_rx_bd`
 *   entries in the host-memory RX return ring that the NIC fills in via
 *   DMA.  sys/dev/netif/bge/if_bge.c:
 *
 *    3058:  cur_rx = &sc->bge_ldata.bge_rx_return_ring
 *                          [sc->bge_rx_saved_considx];
 *    3061:  rxidx = cur_rx->bge_idx;               <- NIC-written (DF-1159)
 *    3110:  m = sc->bge_cdata.bge_rx_std_chain[rxidx].bge_mbuf;
 *    3117:  if (bge_newbuf_std(sc, sc->bge_std, 0)) ... <- posts a fresh
 *                                                       2048-byte cluster
 *    3144:  m->m_pkthdr.len = m->m_len = cur_rx->bge_len - ETHER_CRC_LEN;
 *                                          ^^^^^^ NIC-written uint16_t
 *                                                 (if_bgereg.h:2330),
 *                                                 NO MCLBYTES/jumbo bound
 *
 *   The receiving buffers are:
 *     - std ring: m_getcl() cluster, MCLBYTES == 2048, m_adj(ETHER_ALIGN)
 *       => 2046 bytes usable (if_bge.c:1024-1030,1027);
 *     - jumbo ring (bge HAS jumbo support, unlike the bnx sibling
 *       DF-3639): driver-internal pool slot of BGE_JUMBO_FRAMELEN == 9018
 *       bytes, m_adj(ETHER_ALIGN) => 9016 usable (if_bge.c:1087-1114,
 *       if_bgevar.h:56).  The 384 slots are carved from one contiguous
 *       BGE_JMEM DMA block (if_bge.c:910-921), so overflow of the LAST
 *       slot runs past the entire allocation.
 *
 *   A faulty or malicious NIC (firmware compromise, PCIe DMA attack,
 *   erratum) that writes bge_len > 2050 (std) / > 9020 (jumbo) into the
 *   return-ring BD makes the driver hand the network stack an mbuf
 *   describing up to 65531 bytes inside the small buffer:
 *
 *     - ether_input (sys/net/if_ethersubr.c:1512) runs ETHER_BPF_MTAP()
 *       on it => the bpf(4) tap copies up to ~63.5 KB of kernel heap
 *       PAST the cluster out to the capturing socket (kernel heap info
 *       disclosure);
 *     - IP-stack header validation and socket copies read the same OOB
 *       range (further leak / fault when the walk crosses an unmapped
 *       page => panic);
 *     - on !x86_64 builds ONLY (i386), the RX_ALIGNBUG path first does
 *          bcopy(m->m_data, m->m_data + ETHER_ALIGN, cur_rx->bge_len)
 *       (if_bge.c:3138-3141) with the same untrusted length => kernel
 *       heap OOB *WRITE* (CWE-787).  BCM5701 PCI-X sets
 *       BGE_FLAG_RX_ALIGNBUG (if_bge.c:2206-2208).  The audit guest and
 *       all x86_64 kernels compile this out via #if !defined(__x86_64__).
 *
 *   bge_len < ETHER_HDR_LEN + ETHER_CRC_LEN (18) yields a negative
 *   m_len which DragonFly's ether_input discards at
 *   sys/net/if_ethersubr.c:1502-1506 (`m_len < sizeof(ether_header)')
 *   => benign drop (no underflow panic on this path — unlike the bce
 *   sibling DF-3604, where the length field is unsigned in m_len math).
 *
 *   Hardware-layer bounds that a *healthy* NIC enforces (and which this
 *   bug removes as the last line of defense):
 *     - std producer BD len = m->m_len = 2046/9016 (if_bge.c:1070,1136),
 *     - MAC max RX frame BGE_RX_MTU = mtu+14+4+4 (if_bge.c:3769-3770),
 *     - std RCB max frame 1536 for pre-5705 (if_bge.c:1575-1576).
 *
 *   On real hardware the reproduction is:
 *     1. Attach a BCM570x/57xx based NIC (bge0).
 *     2. Have the device DMA a return-ring BD with bge_len = 65535 and
 *        clear error flags (modified firmware / malicious peripheral /
 *        erratum).
 *     3. `tcpdump -i bge0 -w out.pcap` (or any bpf listener) captures
 *        up to 65531 bytes per frame => adjacent kernel heap disclosed.
 *
 *   The audit QEMU guest has virtio-net only (run.log: NO_BROADCOM_
 *   DEVICE); bge is compiled into the kernel (kldstat -v: pci/if_bge)
 *   but bge_attach/bge_rxeof are unreachable there, so this trigger
 *   CANNOT be exercised on it.  See VERDICT.md for the source-level
 *   proof and the guest evidence.
 */
#include <sys/types.h>
#include <stdio.h>

int
main(void)
{
	fprintf(stderr,
	    "DF-3663: this trigger requires bge(4) hardware "
	    "(BCM5700-5723/575x-590x).\n"
	    "On such a system: configure the NIC, force the device to write\n"
	    "bge_len > 2050 (std ring) or > 9020 (jumbo ring) into an RX\n"
	    "return-ring BD, then capture the handed-up frame\n"
	    "(tcpdump -i bge0 -w out.pcap) and verify the captured frame\n"
	    "length exceeds the posted buffer size (2046 std / 9016 jumbo).\n");
	return 0;
}
