⬢ DragonFlyBSD Kernel Audit
DF-4014 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/raid/mps/mps_user.c b/sys/dev/raid/mps/mps_user.c
--- a/sys/dev/raid/mps/mps_user.c	2026-09-17 14:20:44.418606509 +0000
+++ b/sys/dev/raid/mps/mps_user.c	2026-09-17 14:20:44.434606304 +0000
@@ -838,9 +838,18 @@
 		err = mps_wait_command(sc, cm, 30);
 
 		if (err != 0) {
+			/*
+			 * DF-4014: on timeout the command is still owned
+			 * by the chip; freeing it hands a live SMID back
+			 * to the free list while the chip still DMAs into
+			 * it (use-after-free).  Abandon it instead — it
+			 * is reclaimed on the next diag reset (same policy
+			 * as the config-page timeouts).
+			 */
 			err = EIO;
 			mps_dprint(sc, MPS_FAULT, "%s: task management failed",
 			    __func__);
+			goto Ret;
 		}
 		/*
 		 * Copy the reply data and sense data to user space.
@@ -972,13 +981,21 @@
 
 	mps_lock(sc);
 
+	/*
+	 * DF-4014: mps_wait_command() returning ETIMEDOUT leaves the
+	 * command enqueued with the chip and its SGL pointing at
+	 * cm->cm_data.  The old error path kfree'd cm->cm_data and
+	 * mps_free_command()'d the slot immediately —
+	 * free-while-in-flight.  Abandon the command (reclaimed at the
+	 * next diag reset).
+	 */
 	err = mps_wait_command(sc, cm, 30);
 
 	if (err) {
 		mps_printf(sc, "%s: invalid request: error %d\n", __func__,
 		    err);
 		mps_unlock(sc);
-		goto RetFreeUnlocked;
+		goto Ret;
 	}
 
 	/*