⬢ DragonFlyBSD Kernel Audit
DF-5802 / fix.diff
← back to finding ↓ download raw
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -2676,9 +2676,30 @@
 	pmap = vm_map_pmap(map);
 	start = entry->ba.start;
 	end = entry->ba.end;
-	fictitious = entry->ba.object &&
-			((entry->ba.object->type == OBJT_DEVICE) ||
-			 (entry->ba.object->type == OBJT_MGTDEVICE));
+
+	/*
+	 * Match vm_fault_wire(): UKSMAP entries have no VM object and the
+	 * fault path enters their pages via a fictitious vm_page without
+	 * any vm_page_wire() accounting, so they must not be unwired here
+	 * either.  OBJT_DEVICE and OBJT_MGTDEVICE backing objects use
+	 * fictitious pages as well.  pmap_unwire() returns an unchecked
+	 * PHYS_TO_VM_PAGE() for such ptes, which is a wild vm_page_t for
+	 * UKSMAP device addresses above Maxmem.
+	 */
+	switch (entry->maptype) {
+	case VM_MAPTYPE_NORMAL:
+	case VM_MAPTYPE_VPAGETABLE:
+		fictitious = entry->ba.object &&
+			     ((entry->ba.object->type == OBJT_DEVICE) ||
+			      (entry->ba.object->type == OBJT_MGTDEVICE));
+		break;
+	case VM_MAPTYPE_UKSMAP:
+		fictitious = TRUE;
+		break;
+	default:
+		fictitious = FALSE;
+		break;
+	}
 	if (entry->eflags & MAP_ENTRY_KSTACK)
 		start += PAGE_SIZE;