diff --git a/sys/dev/drm/amd/amdgpu/amdgpu_vm.c b/sys/dev/drm/amd/amdgpu/amdgpu_vm.c --- a/sys/dev/drm/amd/amdgpu/amdgpu_vm.c +++ b/sys/dev/drm/amd/amdgpu/amdgpu_vm.c @@ -2507,9 +2507,16 @@ /* make sure object fit at this offset */ eaddr = saddr + size - 1; - if (saddr >= eaddr || - (bo && offset + size > amdgpu_bo_size(bo))) + if (saddr >= eaddr) return -EINVAL; + /* DF-1257: 'offset + size' wraps mod 2^64 and bypasses the bound. + * Check the range without an overflowing addition: size must fit in + * the BO, and offset must not run past the end. */ + if (bo) { + uint64_t __bo_sz = amdgpu_bo_size(bo); + if (size > __bo_sz || offset > __bo_sz - size) + return -EINVAL; + } saddr /= AMDGPU_GPU_PAGE_SIZE; eaddr /= AMDGPU_GPU_PAGE_SIZE; @@ -2572,9 +2579,16 @@ /* make sure object fit at this offset */ eaddr = saddr + size - 1; - if (saddr >= eaddr || - (bo && offset + size > amdgpu_bo_size(bo))) + if (saddr >= eaddr) return -EINVAL; + /* DF-1257: 'offset + size' wraps mod 2^64 and bypasses the bound. + * Check the range without an overflowing addition: size must fit in + * the BO, and offset must not run past the end. */ + if (bo) { + uint64_t __bo_sz = amdgpu_bo_size(bo); + if (size > __bo_sz || offset > __bo_sz - size) + return -EINVAL; + } /* Allocate all the needed memory */ mapping = kmalloc(sizeof(*mapping), M_DRM, GFP_KERNEL);