⬢ DragonFlyBSD Kernel Audit
DF-5450 / fix.combined.diff
← back to finding ↓ download raw
--- a/sys/platform/pc64/x86_64/nexus.c
+++ b/sys/platform/pc64/x86_64/nexus.c
@@ -374,8 +374,11 @@
 
 	switch (type) {
 	case SYS_RES_IRQ:
-		KASSERT(cpuid >= 0 && cpuid < ncpus,
-		    ("nexus invalid cpuid: %d", cpuid));
+		if (cpuid < 0 || cpuid >= ncpus) {
+			kprintf("nexus_alloc_resource: invalid cpuid %d for "
+			    "SYS_RES_IRQ allocation\n", cpuid);
+			return 0;
+		}
 		rm = &irq_rman[cpuid];
 		break;
 
@@ -426,6 +429,17 @@
 	 */
 	if (rman_get_bustag(r) == X86_64_BUS_SPACE_MEM) {
 		caddr_t vaddr = 0;
+		int error;
+
+		/*
+		 * The mapping step must happen exactly once.  pmap_mapdev()
+		 * is not idempotent while rman_activate_resource() is:
+		 * re-activating an already RF_ACTIVE resource must not
+		 * create a second kernel_map range, or the first one is
+		 * orphaned (permanent KVA leak + stale RW PTEs).
+		 */
+		if (rman_get_flags(r) & RF_ACTIVE)
+			return (rman_activate_resource(r));
 
 		if (rman_get_end(r) < 1024 * 1024) {
 			/*
@@ -446,6 +460,14 @@
 		rman_set_virtual(r, vaddr);
 		/* IBM-PC: the type of bus_space_handle_t is u_int */
 		rman_set_bushandle(r, (bus_space_handle_t) vaddr);
+		error = rman_activate_resource(r);
+		if (error != 0 && rman_get_end(r) >= 1024 * 1024) {
+			/* roll back the mapping we just created */
+			pmap_unmapdev((vm_offset_t)vaddr,
+			    (vm_size_t)rman_get_size(r));
+			rman_set_virtual(r, 0);
+		}
+		return (error);
 	}
 	return (rman_activate_resource(r));
 }
@@ -564,8 +586,6 @@
 	struct resource_list_entry *rle;
 
 	rle = resource_list_find(rl, type, rid);
-	device_printf(child, "type %d  rid %d  startp %p  countp %p - got %p\n",
-		      type, rid, startp, countp, rle);
 	if (!rle)
 		return(ENOENT);
 	if (startp)