⬢ DragonFlyBSD Kernel Audit
DF-3825 / fix.diff
← back to finding ↓ download raw
--- /home/maxx/dfbsd/dfbsd/sys/dev/raid/asr/asr.c	2026-06-29 12:51:19.000000000 +0000
+++ /tmp/opencode/fix/asr.c	2026-09-16 10:59:46.460872200 +0000
@@ -722,10 +722,26 @@
 	}
 
 	/*
-	 * Wait for this board to report a finished instruction.
+	 * Wait for this board to report a finished instruction, bounded
+	 * (a wedged adapter must fail the command, not hang the kernel).
 	 */
-	while ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) {
-		(void)asr_intr (sc);
+	{
+		u_int poll = 30 * 100;	/* ~30s of 10ms polls */
+		while (((ccb->ccb_h.status & CAM_STATUS_MASK)
+		  == CAM_REQ_INPROG) && (--poll != 0)) {
+			(void)asr_intr(sc);
+			if ((ccb->ccb_h.status & CAM_STATUS_MASK)
+			  != CAM_REQ_INPROG)
+				break;
+			crit_exit();
+			DELAY(10000);
+			crit_enter();
+		}
+		if ((ccb->ccb_h.status & CAM_STATUS_MASK)
+		  == CAM_REQ_INPROG) {
+			ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+			ccb->ccb_h.status |= CAM_CMD_TIMEOUT;
+		}
 	}
 
 	/* Re-enable Interrupts */
@@ -1250,8 +1266,15 @@
 		 * good thing. In a production system, however, one may wish
 		 * to instead take the card off-line ...
 		 */
-		/* Wait Forever */
-		while (ASR_resetIOP(sc) == 0);
+		{
+			/* Bounded retries: an unresponsive IOP must take
+			 * the adapter off-line, not spin inside crit. */
+			int retry;
+			for (retry = 0; retry < 60; ++retry) {
+				if (ASR_resetIOP(sc) != 0)
+					break;
+			}
+		}
 	}
 	retVal = ASR_init (sc);
 	crit_exit();
@@ -1887,9 +1910,15 @@
 		u_long size, addr;
 
 		/*
-		 *	Wait for a response (Poll).
+		 *	Wait for a response (Poll), bounded.
 		 */
-		while (*Reply_Ptr < I2O_EXEC_OUTBOUND_INIT_REJECTED);
+		{
+			u_int delay = 300;	/* up to ~3s */
+			while ((*Reply_Ptr < I2O_EXEC_OUTBOUND_INIT_REJECTED)
+			 && (--delay != 0)) {
+				DELAY(10000);
+			}
+		}
 		/*
 		 *	Re-enable the interrupts.
 		 */