--- 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;