DF-4326 / fix.diff
--- a/sys/dev/netif/sf/if_sf.c +++ b/sys/dev/netif/sf/if_sf.c @@ -933,6 +933,18 @@ sf_rxeof(struct sf_softc *sc) while (cmpconsidx != cmpprodidx) { struct mbuf *m0; cur_rx = &sc->sf_ldata->sf_rx_clist[cmpconsidx]; + + /* + * sf_endidx is an 11-bit buffer-descriptor index + * DMA-written by the NIC, but the RX buffer ring only + * has SF_RX_DLIST_CNT (256) entries. An out-of-range + * value must not reach the descriptor dereference: + * sf_newbuf() below would write {mbuf pointer, DMA + * address, valid bit} up to ~28KB past the ring, + * i.e. past the whole contigmalloc'd sf_list_data + * block. Drop the completion and resynchronize. + */ + if (cur_rx->sf_endidx >= SF_RX_DLIST_CNT) { + kprintf("sf%d: bogus RX endidx %u, resetting\n", + sc->sf_unit, (unsigned)cur_rx->sf_endidx); + ifp->if_flags &= ~IFF_RUNNING; + sf_init(sc); + return; + } desc = &sc->sf_ldata->sf_rx_dlist_big[cur_rx->sf_endidx]; m = desc->sf_mbuf; SF_INC(cmpconsidx, SF_RX_CLIST_CNT); |