DF-4232 / fix.diff
--- a/sys/dev/netif/txp/if_txp.c +++ b/sys/dev/netif/txp/if_txp.c @@ -657,6 +657,22 @@ roff = *r->r_roff; woff = *r->r_woff; + + /* + * The ring cursors are firmware-fed DMA state (DF-4232). Validate + * them against the ring geometry before walking anything: both must + * be descriptor-aligned and inside the ring, else the descriptor + * walk runs off the ring (wild rx_sd deref) or never terminates. + */ + if (((roff | woff) & (sizeof(struct txp_rx_desc) - 1)) != 0 || + roff >= (RX_ENTRIES * sizeof(struct txp_rx_desc)) || + woff >= (RX_ENTRIES * sizeof(struct txp_rx_desc))) { + if_printf(ifp, "invalid rx ring indices 0x%x/0x%x\n", roff, woff); + IFNET_STAT_INC(ifp, ierrors, 1); + *r->r_roff = *r->r_woff = 0; + return; + } + rxd = r->r_desc + (roff / sizeof(struct txp_rx_desc)); while (roff != woff) { @@ -1415,6 +1431,21 @@ struct txp_hostvar *hv = sc->sc_hostvar; struct txp_rsp_desc *rsp; + /* + * Response-ring cursors are firmware-fed DMA state (DF-4232): + * validate before computing rsp = base + ridx, and never loop on a + * write index that no aligned walk can ever reach. + */ + if ((ridx & (sizeof(struct txp_rsp_desc) - 1)) != 0 || + ridx >= sc->sc_rspring.size || + (hv->hv_resp_write_idx & (sizeof(struct txp_rsp_desc) - 1)) != 0 || + hv->hv_resp_write_idx >= sc->sc_rspring.size) { + if_printf(&sc->sc_arpcom.ac_if, "invalid response indices " + "0x%x/0x%x\n", ridx, hv->hv_resp_write_idx); + hv->hv_resp_read_idx = hv->hv_resp_write_idx = 0; + return (-1); + } + while (ridx != hv->hv_resp_write_idx) { rsp = (struct txp_rsp_desc *)(((u_int8_t *)sc->sc_rspring.base) + ridx); |