]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/amdgpu: Make SR-IOV critical region checks overflow-safe
authorSrinivasan Shanmugam <srinivasan.shanmugam@amd.com>
Wed, 22 Oct 2025 12:16:26 +0000 (17:46 +0530)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 28 Oct 2025 13:52:44 +0000 (09:52 -0400)
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>
drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c

index 66e9cd1035974cc734e394b039b37f3fbdec4ac2..45f2ad083338b46ba61bd340aa8198e8056387d3 100644 (file)
@@ -937,9 +937,10 @@ static uint8_t amdgpu_virt_crit_region_calc_checksum(uint8_t *buf_start, uint8_t
 int amdgpu_virt_init_critical_region(struct amdgpu_device *adev)
 {
        struct amd_sriov_msg_init_data_header *init_data_hdr = NULL;
-       uint32_t init_hdr_offset = adev->virt.init_data_header.offset;
-       uint32_t init_hdr_size = adev->virt.init_data_header.size_kb << 10;
-       uint64_t vram_size;
+       u64 init_hdr_offset = adev->virt.init_data_header.offset;
+       u64 init_hdr_size = (u64)adev->virt.init_data_header.size_kb << 10; /* KB → bytes */
+       u64 vram_size;
+       u64 end;
        int r = 0;
        uint8_t checksum = 0;
 
@@ -957,7 +958,7 @@ int amdgpu_virt_init_critical_region(struct amdgpu_device *adev)
                return -EINVAL;
        vram_size <<= 20;
 
-       if ((init_hdr_offset + init_hdr_size) > vram_size) {
+       if (check_add_overflow(init_hdr_offset, init_hdr_size, &end) || end > vram_size) {
                dev_err(adev->dev, "init_data_header exceeds VRAM size, exiting\n");
                return -EINVAL;
        }