⬢ DragonFlyBSD Kernel Audit
DF-2523 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/disk/trm/trm.c
+++ b/sys/dev/disk/trm/trm.c
@@ -2425,9 +2425,27 @@
 	/* Read Reselected Target Id and LUN */
 	RselTarLunId = trm_reg_read16(TRMREG_SCSI_TARGETID) & 0x1FFF;
 	pDCB = pACB->pLinkDCB;
-	while (RselTarLunId != *((u_int16_t *) &pDCB->TargetID)) {
-	  /* get pDCB of the reselect id */
-		pDCB = pDCB->pNextDCB;
+	if (pDCB != NULL) {
+		int n = pACB->DeviceCnt;
+
+		while (n-- > 0 &&
+		    RselTarLunId != *((u_int16_t *) &pDCB->TargetID)) {
+		  /* get pDCB of the reselect id (list is circular) */
+			pDCB = pDCB->pNextDCB;
+		}
+		if (n < 0)
+			pDCB = NULL;
+	}
+	if (pDCB == NULL) {
+		/*
+		 * Reselection from a target/LUN with no DCB (malicious
+		 * or glitching device).  Never spin forever at interrupt
+		 * context: drop the connection and let the bus recover.
+		 */
+		trm_reg_write8(STOPDMAXFER, TRMREG_DMA_CONTROL);
+		trm_reg_write16((DO_CLRFIFO | DO_HWRESELECT),
+		    TRMREG_SCSI_CONTROL);
+		return;
 	}
 
 	pACB->pActiveDCB = pDCB;