⬢ DragonFlyBSD Kernel Audit
DF-3604 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/netif/bce/if_bce.c
+++ b/sys/dev/netif/bce/if_bce.c
@@ -4393,11 +4393,24 @@ bce_rx_intr(struct bce_rx_ring *rxr, int count, uint16_t hw_cons)
 			l2fhdr = mtod(m, struct l2_fhdr *);
 
 			len = l2fhdr->l2_fhdr_pkt_len;
 			status = l2fhdr->l2_fhdr_status;
 
+			/*
+			 * Sanity check the NIC-reported frame length before
+			 * using it: pkt_len covers l2_fhdr + pad + frame + FCS
+			 * and must fit in the posted MCLBYTES cluster.  Out of
+			 * range values (faulty/malicious device or firmware
+			 * erratum) would otherwise set m_len past the cluster
+			 * (heap OOB read) or underflow the unsigned length
+			 * below (m_len ~ 4GB, guaranteed panic).
+			 */
+			if (len < sizeof(struct l2_fhdr) + ETHER_ALIGN +
+			    ETHER_CRC_LEN || len > MCLBYTES) {
+				IFNET_STAT_INC(ifp, ierrors, 1);
+
+				/* Reuse the mbuf for a new frame. */
+				bce_setup_rxdesc_std(rxr, sw_chain_prod,
+				    &sw_prod_bseq);
+				m = NULL;
+				goto bce_rx_int_next_rx;
+			}
 			len -= ETHER_CRC_LEN;
 
 			/* Check the received frame for errors. */
 			if (status & (L2_FHDR_ERRORS_BAD_CRC |
 				      L2_FHDR_ERRORS_PHY_DECODE |