drm/amdgpu: validate the parameters of bo mapping operations more clearly
commit 6fef2d4c00b5b8561ad68dd2b68173f5c6af1e75 upstream.
Verify the parameters of
amdgpu_vm_bo_(map/replace_map/clearing_mappings) in one common place.
Fixes: dc54d3d174
("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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
2ef607ea10
commit
1fd7db5c16
@@ -2201,6 +2201,37 @@ static void amdgpu_vm_bo_insert_map(struct amdgpu_device *adev,
|
|||||||
trace_amdgpu_vm_bo_map(bo_va, mapping);
|
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
|
* amdgpu_vm_bo_map - map bo inside a vm
|
||||||
*
|
*
|
||||||
@@ -2227,21 +2258,14 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
|
|||||||
struct amdgpu_bo *bo = bo_va->base.bo;
|
struct amdgpu_bo *bo = bo_va->base.bo;
|
||||||
struct amdgpu_vm *vm = bo_va->base.vm;
|
struct amdgpu_vm *vm = bo_va->base.vm;
|
||||||
uint64_t eaddr;
|
uint64_t eaddr;
|
||||||
|
int r;
|
||||||
|
|
||||||
/* validate the parameters */
|
r = amdgpu_vm_verify_parameters(adev, bo, saddr, offset, size);
|
||||||
if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || size & ~PAGE_MASK)
|
if (r)
|
||||||
return -EINVAL;
|
return r;
|
||||||
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;
|
|
||||||
|
|
||||||
saddr /= AMDGPU_GPU_PAGE_SIZE;
|
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);
|
tmp = amdgpu_vm_it_iter_first(&vm->va, saddr, eaddr);
|
||||||
if (tmp) {
|
if (tmp) {
|
||||||
@@ -2294,17 +2318,9 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev,
|
|||||||
uint64_t eaddr;
|
uint64_t eaddr;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* validate the parameters */
|
r = amdgpu_vm_verify_parameters(adev, bo, saddr, offset, size);
|
||||||
if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || size & ~PAGE_MASK)
|
if (r)
|
||||||
return -EINVAL;
|
return r;
|
||||||
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;
|
|
||||||
|
|
||||||
/* Allocate all the needed memory */
|
/* Allocate all the needed memory */
|
||||||
mapping = kmalloc(sizeof(*mapping), GFP_KERNEL);
|
mapping = kmalloc(sizeof(*mapping), GFP_KERNEL);
|
||||||
@@ -2318,7 +2334,7 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
saddr /= AMDGPU_GPU_PAGE_SIZE;
|
saddr /= AMDGPU_GPU_PAGE_SIZE;
|
||||||
eaddr /= AMDGPU_GPU_PAGE_SIZE;
|
eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE;
|
||||||
|
|
||||||
mapping->start = saddr;
|
mapping->start = saddr;
|
||||||
mapping->last = eaddr;
|
mapping->last = eaddr;
|
||||||
@@ -2405,10 +2421,14 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev,
|
|||||||
struct amdgpu_bo_va_mapping *before, *after, *tmp, *next;
|
struct amdgpu_bo_va_mapping *before, *after, *tmp, *next;
|
||||||
LIST_HEAD(removed);
|
LIST_HEAD(removed);
|
||||||
uint64_t eaddr;
|
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;
|
saddr /= AMDGPU_GPU_PAGE_SIZE;
|
||||||
eaddr /= AMDGPU_GPU_PAGE_SIZE;
|
eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE;
|
||||||
|
|
||||||
/* Allocate all the needed memory */
|
/* Allocate all the needed memory */
|
||||||
before = kzalloc(sizeof(*before), GFP_KERNEL);
|
before = kzalloc(sizeof(*before), GFP_KERNEL);
|
||||||
|
Reference in New Issue
Block a user