Skip to content

Commit 1fd7db5

Browse files
xinhui pangregkh
authored andcommitted
drm/amdgpu: validate the parameters of bo mapping operations more clearly
commit 6fef2d4 upstream. Verify the parameters of amdgpu_vm_bo_(map/replace_map/clearing_mappings) in one common place. Fixes: dc54d3d ("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>
1 parent 2ef607e commit 1fd7db5

File tree

1 file changed

+46
-26
lines changed

1 file changed

+46
-26
lines changed

drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c

Lines changed: 46 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2201,6 +2201,37 @@ static void amdgpu_vm_bo_insert_map(struct amdgpu_device *adev,
22012201
trace_amdgpu_vm_bo_map(bo_va, mapping);
22022202
}
22032203

2204+
/* Validate operation parameters to prevent potential abuse */
2205+
static int amdgpu_vm_verify_parameters(struct amdgpu_device *adev,
2206+
struct amdgpu_bo *bo,
2207+
uint64_t saddr,
2208+
uint64_t offset,
2209+
uint64_t size)
2210+
{
2211+
uint64_t tmp, lpfn;
2212+
2213+
if (saddr & AMDGPU_GPU_PAGE_MASK
2214+
|| offset & AMDGPU_GPU_PAGE_MASK
2215+
|| size & AMDGPU_GPU_PAGE_MASK)
2216+
return -EINVAL;
2217+
2218+
if (check_add_overflow(saddr, size, &tmp)
2219+
|| check_add_overflow(offset, size, &tmp)
2220+
|| size == 0 /* which also leads to end < begin */)
2221+
return -EINVAL;
2222+
2223+
/* make sure object fit at this offset */
2224+
if (bo && offset + size > amdgpu_bo_size(bo))
2225+
return -EINVAL;
2226+
2227+
/* Ensure last pfn not exceed max_pfn */
2228+
lpfn = (saddr + size - 1) >> AMDGPU_GPU_PAGE_SHIFT;
2229+
if (lpfn >= adev->vm_manager.max_pfn)
2230+
return -EINVAL;
2231+
2232+
return 0;
2233+
}
2234+
22042235
/**
22052236
* amdgpu_vm_bo_map - map bo inside a vm
22062237
*
@@ -2227,21 +2258,14 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
22272258
struct amdgpu_bo *bo = bo_va->base.bo;
22282259
struct amdgpu_vm *vm = bo_va->base.vm;
22292260
uint64_t eaddr;
2261+
int r;
22302262

2231-
/* validate the parameters */
2232-
if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || size & ~PAGE_MASK)
2233-
return -EINVAL;
2234-
if (saddr + size <= saddr || offset + size <= offset)
2235-
return -EINVAL;
2236-
2237-
/* make sure object fit at this offset */
2238-
eaddr = saddr + size - 1;
2239-
if ((bo && offset + size > amdgpu_bo_size(bo)) ||
2240-
(eaddr >= adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT))
2241-
return -EINVAL;
2263+
r = amdgpu_vm_verify_parameters(adev, bo, saddr, offset, size);
2264+
if (r)
2265+
return r;
22422266

22432267
saddr /= AMDGPU_GPU_PAGE_SIZE;
2244-
eaddr /= AMDGPU_GPU_PAGE_SIZE;
2268+
eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE;
22452269

22462270
tmp = amdgpu_vm_it_iter_first(&vm->va, saddr, eaddr);
22472271
if (tmp) {
@@ -2294,17 +2318,9 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev,
22942318
uint64_t eaddr;
22952319
int r;
22962320

2297-
/* validate the parameters */
2298-
if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || size & ~PAGE_MASK)
2299-
return -EINVAL;
2300-
if (saddr + size <= saddr || offset + size <= offset)
2301-
return -EINVAL;
2302-
2303-
/* make sure object fit at this offset */
2304-
eaddr = saddr + size - 1;
2305-
if ((bo && offset + size > amdgpu_bo_size(bo)) ||
2306-
(eaddr >= adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT))
2307-
return -EINVAL;
2321+
r = amdgpu_vm_verify_parameters(adev, bo, saddr, offset, size);
2322+
if (r)
2323+
return r;
23082324

23092325
/* Allocate all the needed memory */
23102326
mapping = kmalloc(sizeof(*mapping), GFP_KERNEL);
@@ -2318,7 +2334,7 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev,
23182334
}
23192335

23202336
saddr /= AMDGPU_GPU_PAGE_SIZE;
2321-
eaddr /= AMDGPU_GPU_PAGE_SIZE;
2337+
eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE;
23222338

23232339
mapping->start = saddr;
23242340
mapping->last = eaddr;
@@ -2405,10 +2421,14 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev,
24052421
struct amdgpu_bo_va_mapping *before, *after, *tmp, *next;
24062422
LIST_HEAD(removed);
24072423
uint64_t eaddr;
2424+
int r;
2425+
2426+
r = amdgpu_vm_verify_parameters(adev, NULL, saddr, 0, size);
2427+
if (r)
2428+
return r;
24082429

2409-
eaddr = saddr + size - 1;
24102430
saddr /= AMDGPU_GPU_PAGE_SIZE;
2411-
eaddr /= AMDGPU_GPU_PAGE_SIZE;
2431+
eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE;
24122432

24132433
/* Allocate all the needed memory */
24142434
before = kzalloc(sizeof(*before), GFP_KERNEL);

0 commit comments

Comments
 (0)