]> git.itanic.dy.fi Git - linux-stable/commitdiff
drm/amdgpu: validate the parameters of bo mapping operations more clearly
authorxinhui pan <xinhui.pan@amd.com>
Thu, 11 Apr 2024 03:11:38 +0000 (11:11 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 17 Apr 2024 15:50:43 +0000 (11:50 -0400)
Verify the parameters of
amdgpu_vm_bo_(map/replace_map/clearing_mappings) in one common place.

Fixes: dc54d3d1744d ("drm/amdgpu: implement AMDGPU_VA_OP_CLEAR v2")
Cc: stable@vger.kernel.org
Reported-by: Vlad Stolyarov <hexed@google.com>
Suggested-by: Christian König <christian.koenig@amd.com>
Signed-off-by: xinhui pan <xinhui.pan@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c

index 4299ce386322e7cea27232ae05a1222f62f5a850..94089069c9ada61aa61b7c2b28601b764d47c172 100644 (file)
@@ -1613,6 +1613,37 @@ static void amdgpu_vm_bo_insert_map(struct amdgpu_device *adev,
        trace_amdgpu_vm_bo_map(bo_va, mapping);
 }
 
+/* Validate operation parameters to prevent potential abuse */
+static int amdgpu_vm_verify_parameters(struct amdgpu_device *adev,
+                                         struct amdgpu_bo *bo,
+                                         uint64_t saddr,
+                                         uint64_t offset,
+                                         uint64_t size)
+{
+       uint64_t tmp, lpfn;
+
+       if (saddr & AMDGPU_GPU_PAGE_MASK
+           || offset & AMDGPU_GPU_PAGE_MASK
+           || size & AMDGPU_GPU_PAGE_MASK)
+               return -EINVAL;
+
+       if (check_add_overflow(saddr, size, &tmp)
+           || check_add_overflow(offset, size, &tmp)
+           || size == 0 /* which also leads to end < begin */)
+               return -EINVAL;
+
+       /* make sure object fit at this offset */
+       if (bo && offset + size > amdgpu_bo_size(bo))
+               return -EINVAL;
+
+       /* Ensure last pfn not exceed max_pfn */
+       lpfn = (saddr + size - 1) >> AMDGPU_GPU_PAGE_SHIFT;
+       if (lpfn >= adev->vm_manager.max_pfn)
+               return -EINVAL;
+
+       return 0;
+}
+
 /**
  * amdgpu_vm_bo_map - map bo inside a vm
  *
@@ -1639,21 +1670,14 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
        struct amdgpu_bo *bo = bo_va->base.bo;
        struct amdgpu_vm *vm = bo_va->base.vm;
        uint64_t eaddr;
+       int r;
 
-       /* validate the parameters */
-       if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || size & ~PAGE_MASK)
-               return -EINVAL;
-       if (saddr + size <= saddr || offset + size <= offset)
-               return -EINVAL;
-
-       /* make sure object fit at this offset */
-       eaddr = saddr + size - 1;
-       if ((bo && offset + size > amdgpu_bo_size(bo)) ||
-           (eaddr >= adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT))
-               return -EINVAL;
+       r = amdgpu_vm_verify_parameters(adev, bo, saddr, offset, size);
+       if (r)
+               return r;
 
        saddr /= AMDGPU_GPU_PAGE_SIZE;
-       eaddr /= AMDGPU_GPU_PAGE_SIZE;
+       eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE;
 
        tmp = amdgpu_vm_it_iter_first(&vm->va, saddr, eaddr);
        if (tmp) {
@@ -1706,17 +1730,9 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev,
        uint64_t eaddr;
        int r;
 
-       /* validate the parameters */
-       if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || size & ~PAGE_MASK)
-               return -EINVAL;
-       if (saddr + size <= saddr || offset + size <= offset)
-               return -EINVAL;
-
-       /* make sure object fit at this offset */
-       eaddr = saddr + size - 1;
-       if ((bo && offset + size > amdgpu_bo_size(bo)) ||
-           (eaddr >= adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT))
-               return -EINVAL;
+       r = amdgpu_vm_verify_parameters(adev, bo, saddr, offset, size);
+       if (r)
+               return r;
 
        /* Allocate all the needed memory */
        mapping = kmalloc(sizeof(*mapping), GFP_KERNEL);
@@ -1730,7 +1746,7 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev,
        }
 
        saddr /= AMDGPU_GPU_PAGE_SIZE;
-       eaddr /= AMDGPU_GPU_PAGE_SIZE;
+       eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE;
 
        mapping->start = saddr;
        mapping->last = eaddr;
@@ -1817,10 +1833,14 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev,
        struct amdgpu_bo_va_mapping *before, *after, *tmp, *next;
        LIST_HEAD(removed);
        uint64_t eaddr;
+       int r;
+
+       r = amdgpu_vm_verify_parameters(adev, NULL, saddr, 0, size);
+       if (r)
+               return r;
 
-       eaddr = saddr + size - 1;
        saddr /= AMDGPU_GPU_PAGE_SIZE;
-       eaddr /= AMDGPU_GPU_PAGE_SIZE;
+       eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE;
 
        /* Allocate all the needed memory */
        before = kzalloc(sizeof(*before), GFP_KERNEL);