⬢ DragonFlyBSD Kernel Audit
DF-3892 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/raid/mps/mps.c b/sys/dev/raid/mps/mps.c
index 1111111..2222222 100644
--- a/sys/dev/raid/mps/mps.c
+++ b/sys/dev/raid/mps/mps.c
@@ -857,7 +857,10 @@
 		cm->cm_desc.Default.SMID = i;
 		cm->cm_sc = sc;
 		TAILQ_INIT(&cm->cm_chain_list);
-		callout_init_mp(&cm->cm_callout);
+		/*
+		 * DF-3892: the timeout callbacks (mpssas_scsiio_timeout,
+		 * mpssas_tm_timeout) assume mps_lock is held; tie the
+		 * callout to the lock like mpr(4) does (mpr.c:1539).
+		 */
+		callout_init_lk(&cm->cm_callout, &sc->mps_lock);
 
 		/* XXX Is a failure here a critical problem? */
 		if (bus_dmamap_create(sc->buffer_dmat, 0, &cm->cm_dmamap) == 0)
diff --git a/sys/dev/raid/mps/mps_sas.c b/sys/dev/raid/mps/mps_sas.c
index 1111111..3333333 100644
--- a/sys/dev/raid/mps/mps_sas.c
+++ b/sys/dev/raid/mps/mps_sas.c
@@ -1121,12 +1121,14 @@ mpssas_target_reset_complete(struct mps_softc *sc, struct mps_command *tm)
 static void
 mpssas_tm_timeout(void *data)
 {
 	struct mps_command *tm = data;
 	struct mps_softc *sc = tm->cm_sc;
 
-	mps_lock(sc);
+	/* DF-3892: cm_callout is now lock-tied (callout_init_lk), the
+	 * callout subsystem already holds mps_lock; taking it again
+	 * would self-deadlock. */
+	KKASSERT(lockowned(&sc->mps_lock));
 	mpssas_log_command(tm, "task mgmt %p timed out\n", tm);
 	mps_reinit(sc);
-	mps_unlock(sc);
 }
 
 static void
 mpssas_logical_unit_reset_complete(struct mps_softc *sc, struct mps_command *tm)