⬢ DragonFlyBSD Kernel Audit
DF-4364 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/raid/mps/mps.c b/sys/dev/raid/mps/mps.c
index 3333333..4444444 100644
--- a/sys/dev/raid/mps/mps.c
+++ b/sys/dev/raid/mps/mps.c
@@ -2150,10 +2150,21 @@ mps_request_polled(struct mps_softc *sc, struct mps_command *cm)
 	while ((cm->cm_flags & MPS_CM_FLAGS_COMPLETE) == 0) {
 		mps_intr_locked(sc);
 		DELAY(50 * 1000);
 		if (timeout++ > 1000) {
 			mps_dprint(sc, MPS_FAULT, "polling failed\n");
+			/*
+			 * DF-4364: the request for this SMID is still
+			 * posted to the IOC. Returning with the command
+			 * in flight lets the mps_config.c callers
+			 * (mps_free_command at every `out:' label) free
+			 * it while the hardware owns it; a later reply
+			 * then completes/confuses a reallocated command
+			 * and corrupts the reply free queue.
+			 *
+			 * Mirror the mpr driver fix (mpr_wait_command,
+			 * sys/dev/raid/mpr/mpr.c:3557): diag-reset the
+			 * chip so the stale request can never complete,
+			 * making the caller's free safe.
+			 */
+			mps_reinit(sc);
 			error = ETIMEDOUT;
 			break;
 		}
 	}