⬢ DragonFlyBSD Kernel Audit
DF-2316 / fix.diff
← back to finding ↓ download raw
--- a/sys/bus/isa/pnpparse.c
+++ b/sys/bus/isa/pnpparse.c
@@ -92,6 +92,20 @@
 			 * Got a compatible device id resource.
 			 * Should keep a list of compat ids in the device.
 			 */
+			/*
+			 * The declared length is card-controlled and is
+			 * never validated against the fixed offsets the
+			 * handlers below dereference; a short/zero length
+			 * would read (and for IO_RANGE write) past the
+			 * descriptor -- and, for a descriptor at the end of
+			 * the card stream buffer, past the heap allocation.
+			 * Validate len per tag; skip malformed descriptors.
+			 */
+			if (len < 4) {
+				pnp_printf(id, "bogus compat device length %d\n",
+					   len);
+				break;
+			}
 			bcopy(res, &compat_id, 4);
 			if (isa_get_compatid(dev) == 0)
 				isa_set_compatid(dev, compat_id);
@@ -102,6 +116,11 @@
 				pnp_printf(id, "too many irqs\n");
 				return (1);
 			}
+			if (len < 2) {
+				pnp_printf(id, "bogus irq format length %d\n",
+					   len);
+				break;
+			}
 			if (I16(res) == 0) {
 				/* a null descriptor */
 				config->ic_irqmask[config->ic_nirq] = 0;
@@ -120,6 +139,11 @@
 				pnp_printf(id, "too many drqs\n");
 				return (1);
 			}
+			if (len < 1) {
+				pnp_printf(id, "bogus dma format length %d\n",
+					   len);
+				break;
+			}
 			if (res[0] == 0) {
 				/* a null descriptor */
 				config->ic_drqmask[config->ic_ndrq] = 0;
@@ -138,6 +162,11 @@
 				pnp_printf(id, "too many ports\n");
 				return (1);
 			}
+			if (len < 7) {
+				pnp_printf(id, "bogus io range length %d\n",
+					   len);
+				break;
+			}
 			if (res[6] == 0) {
 				/* a null descriptor */
 				config->ic_port[config->ic_nport].ir_start = 0;
@@ -175,6 +204,11 @@
 				pnp_printf(id, "too many ports\n");
 				return (1);
 			}
+			if (len < 3) {
+				pnp_printf(id, "bogus fixed io range length %d\n",
+					   len);
+				break;
+			}
 			if (res[2] == 0) {
 				/* a null descriptor */
 				config->ic_port[config->ic_nport].ir_start = 0;
@@ -239,6 +273,11 @@
 				pnp_printf(id, "too many memory ranges\n");
 				return (1);
 			}
+			if (len < 9) {
+				pnp_printf(id, "bogus memory range length %d\n",
+					   len);
+				break;
+			}
 			if (I16(res + 7) == 0) {
 				/* a null descriptor */
 				config->ic_mem[config->ic_nmem].ir_start = 0;
@@ -275,6 +314,11 @@
 				pnp_printf(id, "too many memory ranges\n");
 				return (1);
 			}
+			if (len < 17) {
+				pnp_printf(id, "bogus memory32 range length %d\n",
+					   len);
+				break;
+			}
 			if (I32(res + 13) == 0) {
 				/* a null descriptor */
 				config->ic_mem[config->ic_nmem].ir_start = 0;
@@ -305,6 +349,11 @@
 				pnp_printf(id, "too many memory ranges\n");
 				return (1);
 			}
+			if (len < 9) {
+				pnp_printf(id, "bogus fixed memory32 length %d\n",
+					   len);
+				break;
+			}
 			if (I32(res + 5) == 0) {
 				/* a null descriptor */
 				config->ic_mem[config->ic_nmem].ir_start = 0;