DragonFlyBSD Kernel Audit
DF-2281 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/bus/cam/scsi/scsi_sg.c b/sys/bus/cam/scsi/scsi_sg.c
--- a/sys/bus/cam/scsi/scsi_sg.c
+++ b/sys/bus/cam/scsi/scsi_sg.c
@@ -694,8 +694,21 @@
 	/*
 	 * Now set up the data block.  Again, the designers didn't bother
 	 * to make this reliable.
+	 *
+	 * buf_len is an int but uio_resid is size_t; reject anything that
+	 * does not fit (or whose residual is otherwise absurd) instead of
+	 * silently truncating into a negative value that kmalloc/M_ZERO
+	 * would sign-extend into an impossible size.
 	 */
-	buf_len = uio->uio_resid;
+	if (uio->uio_resid > INT_MAX) {
+		error = EINVAL;
+		goto out_ccb;
+	}
+	buf_len = (int)uio->uio_resid;
+	if (buf_len < 0) {
+		error = EINVAL;
+		goto out_ccb;
+	}
 	if (buf_len != 0) {
 		buf = kmalloc(buf_len, M_DEVBUF, M_WAITOK | M_ZERO);
 		error = uiomove(buf, buf_len, uio);
@@ -703,6 +716,10 @@
 			goto out_buf;
 		dir = CAM_DIR_OUT;
 	} else if (hdr->reply_len != 0) {
+		if (hdr->reply_len < 0 || hdr->reply_len > MAXPHYS) {
+			error = EINVAL;
+			goto out_ccb;
+		}
 		buf = kmalloc(hdr->reply_len, M_DEVBUF, M_WAITOK | M_ZERO);
 		buf_len = hdr->reply_len;
 		dir = CAM_DIR_IN;