⬢ DragonFlyBSD Kernel Audit
DF-4164 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/radeon/radeon_pm.c
+++ b/sys/dev/drm/radeon/radeon_pm.c
@@ -147,13 +147,21 @@
 {
 	struct radeon_bo *bo, *n;
 
-	if (list_empty(&rdev->gem.objects))
-		return;
-
+	/*
+	 * gem.objects is mutated under rdev->gem.mutex by GEM create
+	 * (radeon_gem.c) and by radeon_ttm_bo_destroy()'s list_del+kfree
+	 * (radeon_object.c) -- both reachable from unprivileged ioctls /
+	 * handle close while a pm clock change runs here. Hold the mutex
+	 * or the walk can touch a bo freed mid-loop. All gem.mutex
+	 * holders only guard pure list operations, so nesting it around
+	 * ttm_bo_unmap_virtual() introduces no lock-order inversion.
+	 */
+	mutex_lock(&rdev->gem.mutex);
 	list_for_each_entry_safe(bo, n, &rdev->gem.objects, list) {
 		if (bo->tbo.mem.mem_type == TTM_PL_VRAM)
 			ttm_bo_unmap_virtual(&bo->tbo);
 	}
+	mutex_unlock(&rdev->gem.mutex);
 }
 
 static void radeon_sync_with_vblank(struct radeon_device *rdev)