DragonFlyBSD Kernel Audit
DF-1238 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/disk/trm/trm.c b/sys/dev/disk/trm/trm.c
index 73425d7c..9870a7de 100644
--- a/sys/dev/disk/trm/trm.c
+++ b/sys/dev/disk/trm/trm.c
@@ -2425,9 +2425,29 @@ trm_Reselect(PACB pACB)
 	/* 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;
+	{
+		u_int16_t dcb_i;
+		for (dcb_i = 0; dcb_i < pACB->DeviceCnt; dcb_i++) {
+			if (RselTarLunId == *((u_int16_t *) &pDCB->TargetID))
+				break;
+			/* get pDCB of the reselect id */
+			pDCB = pDCB->pNextDCB;
+		}
+		if (dcb_i >= pACB->DeviceCnt) {
+			/*
+			 * No DCB matched the reselected target/LUN.  A
+			 * malicious or misbehaving target could reselect with
+			 * an unknown ID/LUN and loop the old unbounded walk
+			 * forever in interrupt context.  Treat as an
+			 * unexpected reselection and abort via TmpSRB.
+			 */
+			pSRB = &pACB->TmpSRB;
+			pSRB->SRBState = SRB_UNEXPECT_RESEL;
+			pACB->pActiveDCB = NULL;
+			pDCB->pActiveSRB = pSRB;
+			trm_EnableMsgOutAbort1(pACB, pSRB);
+			return;
+		}
 	}
 
 	pACB->pActiveDCB = pDCB;