⬢ DragonFlyBSD Kernel Audit
DF-4615 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/raid/ips/ips.c b/sys/dev/raid/ips/ips.c
index 1111111..2222222 100644
--- a/sys/dev/raid/ips/ips.c
+++ b/sys/dev/raid/ips/ips.c
@@ -672,8 +672,12 @@ exit:
 	bus_dmamem_free(dmatag, sc->copper_queue, dmamap);
 	bus_dma_tag_destroy(dmatag);
+	sc->copper_queue = NULL;
 	return error;
 }
 
+/* free the current status queue (if any) - used before re-allocating on
+ * reinit and on driver teardown */
+static void ips_copperhead_queue_free(ips_softc_t *sc);
+
 static int
 ips_copperhead_queue_init(ips_softc_t *sc)
 {
@@ -647,6 +651,9 @@ static int
 	bus_dmamap_t dmamap = NULL;
 	int error;
 
+	/* DF-4615: a reinit must not leak the previous queue mapping */
+	ips_copperhead_queue_free(sc);
+
 	if (bus_dma_tag_create(	/* parent    */	sc->adapter_dmatag,
@@ -727,7 +734,10 @@ ips_copperhead_reinit(ips_softc_t *sc, int force)
 	ips_write_2(sc, COPPER_REG_CCCR, 0x1000 | COPPER_ILE_BIT);
 	ips_write_1(sc, COPPER_REG_SCPR, COPPER_EBM_BIT);
-	ips_copperhead_queue_init(sc);
+	if (ips_copperhead_queue_init(sc) != 0) {
+		device_printf(sc->dev, "status queue init failed\n");
+		return 1;
+	}
 	ips_write_1(sc, COPPER_REG_HISR, COPPER_GHI_BIT);