⬢ DragonFlyBSD Kernel Audit
DF-4614 / 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
@@ -118,6 +118,12 @@ static int
 ips_cmdqueue_free(ips_softc_t *sc)
 {
 	int i, error = -1;
 	ips_command_t *command;
 
 	crit_enter();
+	if (sc->commandarray == NULL) {
+		crit_exit();
+		return 0;
+	}
 	if (sc->used_commands == 0) {
@@ -137,9 +143,11 @@ ips_cmdqueue_free(ips_softc_t *sc)
 		error = 0;
 		sc->state |= IPS_OFFLINE;
+	} else {
+		/* commands still outstanding: do not free the array under
+		 * the interrupt handler; leave it mapped and report busy */
+		crit_exit();
+		return error;
 	}
 	sc->staticcmd = NULL;
 	kfree(sc->commandarray, M_IPSBUF);
+	sc->commandarray = NULL;
 	crit_exit();
 	return error;
 }
@@ -411,7 +419,9 @@ ips_adapter_init(ips_softc_t *sc)
 	 * create one command buffer until we know how many commands this card
 	 * can handle
 	 */
 	sc->max_cmds = 1;
-	ips_cmdqueue_init(sc);
+	if (ips_cmdqueue_init(sc)) {
+		device_printf(sc->dev, "initial command queue alloc failed\n");
+		goto error;
+	}
 	callout_init(&sc->timer);