⬢ DragonFlyBSD Kernel Audit
DF-5443 / fix.diff
← back to finding ↓ download raw
--- a/sys/bus/isa/pnp.c	2026-06-29 12:51:18.000000000 +0000
+++ b/sys/bus/isa/pnp.c	2026-10-05 16:42:46.510646162 +0000
@@ -98,6 +98,9 @@
         { 0 }
 };
 
+/* Sanity cap on resource data ingested from one card */
+#define PNP_MAX_RESOURCE_DATA	65536
+
 /* The READ_DATA port that we are using currently */
 static int pnp_rd_port;
 
@@ -257,8 +260,17 @@
 	for (i = 0; i < config->ic_nmem; i++) {
 		u_int32_t start = config->ic_mem[i].ir_start;
 		u_int32_t size =  config->ic_mem[i].ir_size;
-		if (start & 0xff)
-			panic("pnp_set_config: bogus memory assignment");
+		if (start & 0xff) {
+			/*
+			 * Card-supplied descriptors can carry sub-256
+			 * granularity while the memory registers only
+			 * encode bits [23:8].  Degrade gracefully instead
+			 * of taking the system down.
+			 */
+			kprintf("pnp_set_config: misaligned memory "
+				"assignment %#x\n", start);
+			start &= ~0xffu;
+		}
 		pnp_write(PNP_MEM_BASE_HIGH(i), (start >> 16) & 0xff);
 		pnp_write(PNP_MEM_BASE_LOW(i), (start >> 8) & 0xff);
 		pnp_write(PNP_MEM_RANGE_HIGH(i), (size >> 16) & 0xff);
@@ -426,6 +438,13 @@
 			
 		switch (PNP_SRES_NUM(tag)) {
 		case PNP_TAG_LOGICAL_DEVICE:
+			if (ldn > 255) {
+				/* LDN register is 8-bit; stop ingesting. */
+				device_printf(parent,
+					      "too many logical devices\n");
+				scanning = 0;
+				break;
+			}
 			/*
 			 * Parse the resources for the previous
 			 * logical device (if any).
@@ -514,12 +533,21 @@
 		space += extra;
 	}
 
+	/*
+	 * Publish the (possibly reallocated) buffer before attempting the
+	 * read.  If the read comes up short the caller must still see the
+	 * live allocation so it frees it exactly once; the old code left
+	 * *resourcesp pointing at the freed pre-growth buffer, causing a
+	 * double free in pnp_isolation_protocol() and leaking the grown
+	 * buffer.
+	 */
+	*resourcesp = resources;
+	*spacep = space;
+
 	if (pnp_get_resource_info(resources + len, amount) != amount)
 		return EINVAL;
 	len += amount;
 
-	*resourcesp = resources;
-	*spacep = space;
 	*lenp = len;
 
 	return 0;
@@ -544,6 +572,12 @@
 	error = 0;
 	done = 0;
 	while (!done) {
+		if (len > PNP_MAX_RESOURCE_DATA) {
+			kprintf("pnp_read_resources: too much resource "
+				"data\n");
+			error = EINVAL;
+			goto out;
+		}
 		error = pnp_read_bytes(1, &resources, &space, &len);
 		if (error)
 			goto out;
--- a/sys/bus/isa/pnpparse.c	2026-06-29 12:51:18.000000000 +0000
+++ b/sys/bus/isa/pnpparse.c	2026-10-05 16:43:21.606196774 +0000
@@ -297,6 +297,16 @@
 			    I32(res + 5) + I32(res + 13) - 1;
 			config->ic_mem[config->ic_nmem].ir_size = I32(res + 13);
 			config->ic_mem[config->ic_nmem].ir_align = I32(res + 9);
+			/*
+			 * The PnP memory registers encode bits [23:8]; enforce
+			 * 256-byte granularity so the allocator cannot hand
+			 * pnp_set_config() a base it cannot program.
+			 */
+			if (config->ic_mem[config->ic_nmem].ir_align < 0x100)
+				config->ic_mem[config->ic_nmem].ir_align = 0x100;
+			config->ic_mem[config->ic_nmem].ir_start =
+			    (config->ic_mem[config->ic_nmem].ir_start + 0xff) &
+			    ~0xffu;
 			config->ic_nmem++;
 			break;
 
@@ -320,11 +330,13 @@
 					   I32(res + 1) + I32(res + 5) - 1,
 					   I32(res + 5));
 			}
-			config->ic_mem[config->ic_nmem].ir_start = I32(res + 1);
+			/* 256-byte granularity, as above */
+			config->ic_mem[config->ic_nmem].ir_start =
+			    (I32(res + 1) + 0xff) & ~0xffu;
 			config->ic_mem[config->ic_nmem].ir_end =
 			    I32(res + 1) + I32(res + 5) - 1;
 			config->ic_mem[config->ic_nmem].ir_size = I32(res + 5);
-			config->ic_mem[config->ic_nmem].ir_align = 1;
+			config->ic_mem[config->ic_nmem].ir_align = 0x100;
 			config->ic_nmem++;
 			break;