DragonFlyBSD Kernel Audit
DF-1227 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/raid/mpr/mpr_user.c b/sys/dev/raid/mpr/mpr_user.c
--- a/sys/dev/raid/mpr/mpr_user.c
+++ b/sys/dev/raid/mpr/mpr_user.c
@@ -806,6 +806,22 @@
 		goto RetFreeUnlocked;
 	}
 
+	/*
+	 * Cap the user-supplied data sizes to the controller's max I/O.
+	 * Without this, mpr_build_nvme_prp() would be driven past its single
+	 * allocated PRP-list page (one PAGE_SIZE buffer per command, holding
+	 * PAGE_SIZE/8 entries) and write PRP entries off the end of that
+	 * buffer, overflowing the kernel heap with attacker-controlled
+	 * physical addresses.
+	 */
+	if (data->DataSize > sc->maxio || data->DataOutSize > sc->maxio) {
+		mpr_dprint(sc, MPR_FAULT, "%s: data size too large "
+		    "(in %d out %d > maxio %u)\n", __func__, data->DataSize,
+		    data->DataOutSize, sc->maxio);
+		err = EINVAL;
+		goto RetFreeUnlocked;
+	}
+
 	function = tmphdr.Function;
 	mpr_dprint(sc, MPR_USER, "%s: Function %02X MsgFlags %02X\n", __func__,
 	    function, tmphdr.MsgFlags);