DragonFlyBSD Kernel Audit
DF-1040 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/bus/pccard/pccard_cis.c b/sys/bus/pccard/pccard_cis.c
--- a/sys/bus/pccard/pccard_cis.c
+++ b/sys/bus/pccard/pccard_cis.c
@@ -409,6 +409,27 @@
 				goto done;
 			}
 
+			/*
+			 * Validate the link target before dereferencing it.
+			 * longlink_addr and mfc[].addr are full 32-bit card-supplied
+			 * values; without this check a malicious card makes us
+			 * bus_space_read_1() at mult*ptr far outside the CIS mapping
+			 * and page-faults the kernel (DF-1040).  Compare ptr against
+			 * the window size in index units to avoid multiplication
+			 * overflow on 32-bit platforms (where mult*ptr could wrap to
+			 * ~0).  The coarse first check also catches ptr values so
+			 * large that ptr+4 would itself wrap a 32-bit unsigned.
+			 * We need room for the 5-byte LINKTARGET header
+			 * (code, length, "C","I","S").
+			 */
+			if (tuple.ptr >= PCCARD_CIS_SIZE ||
+			    tuple.ptr + 4 >= PCCARD_CIS_SIZE / tuple.mult) {
+				device_printf(dev, "CIS longlink/MFC target %lx "
+				    "out of bounds (mult=%lx)\n", (u_long)tuple.ptr,
+				    (u_long)tuple.mult);
+				continue;
+			}
+
 			/* make sure that the link is valid */
 			tuple.code = pccard_cis_read_1(&tuple, tuple.ptr);
 			if (tuple.code != CISTPL_LINKTARGET) {