⬢ DragonFlyBSD Kernel Audit
DF-2283 / fix.diff
← back to finding ↓ download raw
--- a/sys/bus/cam/scsi/scsi_sg.c
+++ b/sys/bus/cam/scsi/scsi_sg.c
@@ -787,8 +787,20 @@
 	}
 	if (rdwr == NULL) {
 		cam_periph_unlock(periph);
-		if (tsleep(&hstat, PCATCH, "sgnull", 0) == ERESTART)
-			return(EAGAIN);
+		/*
+		 * DF-2283: the &hstat channel has NO wakeup source (it is a
+		 * stack address unique to this invocation; sgdone only ever
+		 * wakeup()s rdwr or &ccb_h.cbfcnp).  Bound the sleep with
+		 * the command timeout so an unmatched pack_id cannot block
+		 * read(2) forever; a timeout means the queue can never
+		 * satisfy this request.
+		 */
+		error = tsleep(&hstat, PCATCH, "sgnull",
+		    sc->sg_timeout ? sc->sg_timeout : 60 * hz);
+		if (error == ERESTART)
+			return (EAGAIN);
+		if (error != 0)		/* EWOULDBLOCK: timed out */
+			return (ENOENT);
 		cam_periph_lock(periph);
 		goto search;
 	}