⬢ DragonFlyBSD Kernel Audit
DF-4562 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/raid/mps/mps_sas_lsi.c
+++ b/sys/dev/raid/mps/mps_sas_lsi.c
@@ -650,6 +650,18 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){
 	if (id == MPS_MAP_BAD_ID) {
 		...
 	}
 	targ = &sassc->targets[id];
+	/*
+	 * DF-4562 hardening: never re-initialize a target slot that is still
+	 * being removed asynchronously (mpssas_prepare_remove's TM has not
+	 * completed) or that still owns commands — TAILQ_INIT would orphan
+	 * them and the completion path would corrupt the re-initialized list.
+	 */
+	if (targ->handle != 0 &&
+	    ((targ->flags & MPSSAS_TARGET_INREMOVAL) ||
+	     !TAILQ_EMPTY(&targ->commands) ||
+	     !TAILQ_EMPTY(&targ->timedout_commands) ||
+	     targ->tm != NULL)) {
+		kprintf("%s: target id %d busy (removal in flight); refusing "
+		    "re-add of handle 0x%04x\n", __func__, id, handle);
+		error = EBUSY;
+		goto out;
+	}
 	targ->devinfo = device_info;
@@ -845,6 +857,14 @@ mpssas_volume_add(struct mps_softc *sc, u16 handle)
 	targ = &sassc->targets[id];
+	if (targ->handle != 0 &&
+	    ((targ->flags & MPSSAS_TARGET_INREMOVAL) ||
+	     !TAILQ_EMPTY(&targ->commands) ||
+	     !TAILQ_EMPTY(&targ->timedout_commands) ||
+	     targ->tm != NULL)) {
+		error = EBUSY;
+		goto out;
+	}
 	targ->tid = id;

NOTE: defensive sketch only (speculative finding DF-4562) — context lines
are abbreviated; not applied to sys/.