Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/amdgpu: Make SR-IOV critical region checks overflow-safe

The function amdgpu_virt_init_critical_region() contained an invalid
check for a negative init_hdr_offset value:

if (init_hdr_offset < 0)

Since init_hdr_offset is an unsigned 32-bit integer, this condition can
never be true and triggers a Smatch warning:

warn: unsigned 'init_hdr_offset' is never less than zero

In addition, the subsequent bounds check: if ((init_hdr_offset +
init_hdr_size) > vram_size) was vulnerable to integer overflow when
adding the two unsigned values. Thus, by promoting offset and size to
64-bit and using check_add_overflow() to safely validate the sum against
VRAM size.

Fixes: 07009df6494d ("drm/amdgpu: Introduce SRIOV critical regions v2 during VF init")
Reported by: Dan Carpenter <dan.carpenter@linaro.org>
Cc: Ellen Pan <yunru.pan@amd.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
Reviewed-by: Ellen Pan <yunru.pan@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Srinivasan Shanmugam and committed by
Alex Deucher
00dc2ff5 102c4f7c

+5 -4
+5 -4
drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
··· 937 937 int amdgpu_virt_init_critical_region(struct amdgpu_device *adev) 938 938 { 939 939 struct amd_sriov_msg_init_data_header *init_data_hdr = NULL; 940 - uint32_t init_hdr_offset = adev->virt.init_data_header.offset; 941 - uint32_t init_hdr_size = adev->virt.init_data_header.size_kb << 10; 942 - uint64_t vram_size; 940 + u64 init_hdr_offset = adev->virt.init_data_header.offset; 941 + u64 init_hdr_size = (u64)adev->virt.init_data_header.size_kb << 10; /* KB → bytes */ 942 + u64 vram_size; 943 + u64 end; 943 944 int r = 0; 944 945 uint8_t checksum = 0; 945 946 ··· 958 957 return -EINVAL; 959 958 vram_size <<= 20; 960 959 961 - if ((init_hdr_offset + init_hdr_size) > vram_size) { 960 + if (check_add_overflow(init_hdr_offset, init_hdr_size, &end) || end > vram_size) { 962 961 dev_err(adev->dev, "init_data_header exceeds VRAM size, exiting\n"); 963 962 return -EINVAL; 964 963 }