DF-3604 / trigger.c
/* * DF-3604 โ bce(4) RX path trusts NIC-DMA'd l2_fhdr_pkt_len * * Trigger (HARDWARE REQUIRED โ cannot run on the audit guest): * * The Broadcom NetXtreme II prepends an `struct l2_fhdr` (16 bytes) to * every frame it DMAs into the posted mbuf cluster (MCLBYTES == 2048): * * +----------------+-----+---------------------+-----+ * | l2_fhdr (16B) | pad | packet data | FCS | * +----------------+-----+---------------------+-----+ * * sys/dev/netif/bce/if_bce.c: * 4396: len = l2fhdr->l2_fhdr_pkt_len; <- value WRITTEN BY THE NIC * 4399: len -= ETHER_CRC_LEN; <- unsigned underflow if < 4 * 4437: m_adj(m, sizeof(struct l2_fhdr) + ETHER_ALIGN); * 4439: m->m_pkthdr.len = m->m_len = len; <- NO MCLBYTES BOUND * * A faulty or malicious NIC (or NIC firmware) that reports * l2_fhdr_pkt_len > MCLBYTES (2048) causes the mbuf to describe up to * 65531 bytes of data inside a 2048-byte cluster. Every subsequent * consumer of the mbuf (ether_input, IP stack, socket copies) reads * past the end of the cluster => kernel heap OOB read of up to ~63.5 KB * (heap info leak into packets readable by an unprivileged local user, * or panic when the walk crosses an unmapped page). * A reported pkt_len < ETHER_CRC_LEN (4) underflows `len` (unsigned * int) to ~4 GB and m->m_len becomes that value => immediate OOB walk * / panic (local DoS). * * On real hardware the reproduction is: * 1. Attach a BCM5706/5708/5709/5716 based NIC (bce0). * 2. Have the device DMA a frame whose l2_fhdr carries an oversized * (or tiny) l2_fhdr_pkt_len โ e.g. via modified device firmware, * a Thunderclap-style peripheral, or a NIC erratum. * 3. Observe the frame handed up the stack with m_len > 2030. * * The audit QEMU guest has virtio-net only; the bce attach path is * unreachable there, so this trigger CANNOT be exercised on it. * See VERDICT.md for the source-level proof and the guest evidence. * * Reference C skeleton (for a guest that *does* have bce hardware, * checks that received mbufs are consistent โ a "canary" harness, not * an exploit): */ #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> int main(void) { fprintf(stderr, "DF-3604: this trigger requires bce(4) hardware (BCM5706..5716).\n" "On such a system: configure the NIC, force the device to report\n" "l2_fhdr_pkt_len > 2048 (or < 4) in the RX l2_fhdr, then capture\n" "the handed-up frame (e.g. tcpdump -i bce0 -w out.pcap) and verify\n" "the captured length exceeds MCLBYTES - sizeof(l2_fhdr) - 2 - 4.\n"); return 0; } |