⬢ DragonFlyBSD Kernel Audit
DF-3720 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/netif/mxge/if_mxge.c
+++ b/sys/dev/netif/mxge/if_mxge.c
@@ -1137,6 +1137,17 @@
 }
 #endif
 
+/*
+ * Firmware-returned SRAM offsets are device-supplied; every pointer we
+ * later PIO-write through must lie inside the mapped SRAM BAR window.
+ */
+static __inline int
+mxge_sram_range_valid(const mxge_softc_t *sc, uint32_t off, uint32_t len)
+{
+	return (off <= (uint32_t)sc->sram_size &&
+		len <= (uint32_t)sc->sram_size - off);
+}
+
 static int
 mxge_reset(mxge_softc_t *sc, int interrupts_setup)
 {
@@ -1220,12 +1231,18 @@
 
 	status |= mxge_send_cmd(sc, MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET,
 	    &cmd);
+	if (status == 0 && !mxge_sram_range_valid(sc, cmd.data0, 4))
+		status = ENXIO;
 	sc->intr_coal_delay_ptr = (volatile uint32_t *)(sc->sram + cmd.data0);
 
 	status |= mxge_send_cmd(sc, MXGEFW_CMD_GET_IRQ_ACK_OFFSET, &cmd);
+	if (status == 0 && !mxge_sram_range_valid(sc, cmd.data0, 8))
+		status = ENXIO;
 	irq_claim = (volatile uint32_t *)(sc->sram + cmd.data0);
 
 	status |= mxge_send_cmd(sc,  MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET, &cmd);
+	if (status == 0 && !mxge_sram_range_valid(sc, cmd.data0, 4))
+		status = ENXIO;
 	sc->irq_deassert = (volatile uint32_t *)(sc->sram + cmd.data0);
 
 	if (status != 0) {
@@ -3290,6 +3307,11 @@
 			cmd.data0 = slice;
 			err = mxge_send_cmd(ss->sc, MXGEFW_CMD_GET_SEND_OFFSET,
 			    &cmd);
+			if (err == 0 &&
+			    !mxge_sram_range_valid(ss->sc, cmd.data0,
+			    (ss->tx.mask + 1) *
+			    sizeof(mcp_kreq_ether_send_t)))
+				err = ENXIO;
 			ss->tx.lanai = (volatile mcp_kreq_ether_send_t *)
 			    (ss->sc->sram + cmd.data0);
 			/* Leave send_go and send_stop as NULL */
@@ -3297,6 +3319,10 @@
 	} else {
 		cmd.data0 = slice;
 		err = mxge_send_cmd(ss->sc, MXGEFW_CMD_GET_SEND_OFFSET, &cmd);
+		if (err == 0 &&
+		    !mxge_sram_range_valid(ss->sc, cmd.data0,
+		    (ss->tx.mask + 1) * sizeof(mcp_kreq_ether_send_t)))
+			err = ENXIO;
 		ss->tx.lanai = (volatile mcp_kreq_ether_send_t *)
 		    (ss->sc->sram + cmd.data0);
 		ss->tx.send_go = (volatile uint32_t *)
@@ -3307,11 +3333,19 @@
 
 	cmd.data0 = slice;
 	err |= mxge_send_cmd(ss->sc, MXGEFW_CMD_GET_SMALL_RX_OFFSET, &cmd);
+	if (err == 0 &&
+	    !mxge_sram_range_valid(ss->sc, cmd.data0,
+	    (ss->rx_data.rx_small.mask + 1) * sizeof(mcp_kreq_ether_recv_t)))
+		err = ENXIO;
 	ss->rx_data.rx_small.lanai =
 	    (volatile mcp_kreq_ether_recv_t *)(ss->sc->sram + cmd.data0);
 
 	cmd.data0 = slice;
 	err |= mxge_send_cmd(ss->sc, MXGEFW_CMD_GET_BIG_RX_OFFSET, &cmd);
+	if (err == 0 &&
+	    !mxge_sram_range_valid(ss->sc, cmd.data0,
+	    (ss->rx_data.rx_big.mask + 1) * sizeof(mcp_kreq_ether_recv_t)))
+		err = ENXIO;
 	ss->rx_data.rx_big.lanai =
 	    (volatile mcp_kreq_ether_recv_t *)(ss->sc->sram + cmd.data0);
 
@@ -3393,6 +3427,10 @@
 		}
 
 		itable = sc->sram + cmd.data0;
+		if (!mxge_sram_range_valid(sc, cmd.data0, NETISR_CPUMAX)) {
+			if_printf(ifp, "bad RSS table offset 0x%x\n", cmd.data0);
+			return EIO;
+		}
 		for (i = 0; i < NETISR_CPUMAX; i++)
 			itable[i] = sc->rdr_table[i];
 
@@ -3410,6 +3448,12 @@
 				return err;
 			}
 			hwkey = sc->sram + cmd.data0;
+			if (!mxge_sram_range_valid(sc, cmd.data0,
+			    MXGE_HWRSS_KEYLEN)) {
+				if_printf(ifp, "bad RSS key offset 0x%x\n",
+				    cmd.data0);
+				return EIO;
+			}
 
 			toeplitz_get_key(swkey, MXGE_HWRSS_KEYLEN);
 			for (i = 0; i < MXGE_HWRSS_KEYLEN; ++i)