⬢ DragonFlyBSD Kernel Audit
DF-4576 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/amd/amdgpu/amdgpu_gem.c
+++ b/sys/dev/drm/amd/amdgpu/amdgpu_gem.c
@@ -633,6 +633,28 @@
 		bo_va = NULL;
 	}
 
+	/*
+	 * Validate the mapping before allocating page tables for it.
+	 * amdgpu_vm_alloc_pts() below commits page-table BOs for the whole
+	 * [va_address, va_address + map_size) range; when amdgpu_vm_bo_map()
+	 * then rejects the mapping (bad offset_in_bo / map_size), those page
+	 * tables stay allocated until VM teardown.  An unprivileged render
+	 * node client can pin ~(map_size >> 18) bytes of GTT per failed
+	 * ioctl with no backing BO, and repeat until GTT is exhausted.
+	 */
+	if (args->operation == AMDGPU_VA_OP_MAP ||
+	    args->operation == AMDGPU_VA_OP_REPLACE) {
+		if (!args->map_size || (args->map_size & AMDGPU_GPU_PAGE_MASK) ||
+		    (args->offset_in_bo & AMDGPU_GPU_PAGE_MASK) ||
+		    args->va_address + args->map_size - 1 < args->va_address ||
+		    args->offset_in_bo + args->map_size < args->offset_in_bo ||
+		    (abo && args->offset_in_bo + args->map_size >
+		     amdgpu_bo_size(abo))) {
+			r = -EINVAL;
+			goto error_backoff;
+		}
+	}
+
 	switch (args->operation) {
 	case AMDGPU_VA_OP_MAP:
 		r = amdgpu_vm_alloc_pts(adev, bo_va->base.vm, args->va_address,