⬢ DragonFlyBSD Kernel Audit
DF-4587 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/ttm/ttm_bo_vm.c
+++ b/sys/dev/drm/ttm/ttm_bo_vm.c
@@ -826,6 +826,15 @@
 	if (vm_obj == NULL)
 		return;
 
+	/*
+	 * DF-4587: cdev_pager_lookup() does NOT take a reference.  The
+	 * pager object's only references are the per-mmap references owned
+	 * by the user's vm_map entries, so hold the object across the
+	 * revocation to keep a concurrent last-unmap from terminating it
+	 * while we operate on it.
+	 */
+	vm_object_hold(vm_obj);
+
 	VM_OBJECT_LOCK(vm_obj);
 #if 1
 	vm_object_page_remove(vm_obj, 0, 0, false);
@@ -847,8 +856,18 @@
 	}
 #endif
 	VM_OBJECT_UNLOCK(vm_obj);
+	vm_object_drop(vm_obj);
 
-	vm_object_deallocate(vm_obj);
+	/*
+	 * DF-4587: DO NOT vm_object_deallocate() here.  This function runs
+	 * on every BO revocation (ttm_bo_handle_move_mem, ttm_bo_swapout,
+	 * radeon_pm), and we hold no reference: each call would drop a
+	 * reference owned by a live mapping, terminate the object while
+	 * mappings are still attached (freed vm_object under live map
+	 * entries) and fire ttm_bo_vm_dtor -> premature ttm_bo_unref().
+	 * The object must die when its last mapping goes away; the dtor
+	 * then releases the mmap's BO reference.
+	 */
 }
 #endif