--- a/sys/dev/netif/re/if_revar.h +++ b/sys/dev/netif/re/if_revar.h @@ -132,6 +132,8 @@ struct callout re_timer; struct mbuf *re_head; struct mbuf *re_tail; + int re_rxchain_len; /* bytes accumulated in re_head */ + int re_rxchain_len; /* bytes accumulated in re_head */ uint32_t re_caps; /* see RE_C_ */ int re_rx_desc_cnt; int re_tx_desc_cnt; --- a/sys/dev/netif/re/if_re.c +++ b/sys/dev/netif/re/if_re.c @@ -291,6 +291,7 @@ m_freem(sc->re_head); sc->re_head = sc->re_tail = NULL; } + sc->re_rxchain_len = 0; } static int @@ -1094,6 +1095,7 @@ sc->re_ldata.re_rx_prodidx = 0; sc->re_head = sc->re_tail = NULL; + sc->re_rxchain_len = 0; return(0); } @@ -1165,9 +1167,11 @@ m->m_len = MCLBYTES; if (sc->re_head == NULL) { sc->re_head = sc->re_tail = m; + sc->re_rxchain_len = m->m_len; } else { sc->re_tail->m_next = m; sc->re_tail = m; + sc->re_rxchain_len += m->m_len; } continue; } else if (sc->re_flags & RE_F_DROP_RXFRAG) { @@ -1193,6 +1197,22 @@ re_free_rxchain(sc); re_setup_rxdesc(sc, i); continue; + } + + /* + * The frame length is device-fed (14-bit GFRAGLEN, + * RE_RXBYTES). A faulty or malicious NIC can claim + * up to 16383 bytes for a single 2048-byte cluster or + * a total larger than the accumulated fragment chain, + * which would hand out-of-bounds kernel heap to the + * network stack. Validate it against the geometry. + */ + if (total_len < ETHER_HDR_LEN + ETHER_CRC_LEN || + total_len > sc->re_rxbuf_size + sc->re_rxchain_len) { + IFNET_STAT_INC(ifp, ierrors, 1); + re_free_rxchain(sc); + re_setup_rxdesc(sc, i); + continue; } /*