From: Dan Carpenter Date: Fri, 23 May 2025 16:05:58 +0000 (+0300) Subject: drm/amdgpu: Fix integer overflow issues in amdgpu_userq_fence.c X-Git-Tag: v6.16-rc1~33^2~1^2~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=98a46a408998102af5c45adce0871acd7967bb59;p=thirdparty%2Flinux.git drm/amdgpu: Fix integer overflow issues in amdgpu_userq_fence.c This patch only affects 32bit systems. There are several integer overflows bugs here but only the "sizeof(u32) * num_syncobj" multiplication is a problem at runtime. (The last lines of this patch). These variables are u32 variables that come from the user. The issue is the multiplications can overflow leading to us allocating a smaller buffer than intended. For the first couple integer overflows, the syncobj_handles = memdup_user() allocation is immediately followed by a kmalloc_array(): syncobj = kmalloc_array(num_syncobj_handles, sizeof(*syncobj), GFP_KERNEL); In that situation the kmalloc_array() works as a bounds check and we haven't accessed the syncobj_handlesp[] array yet so the integer overflow is harmless. But the "num_syncobj" multiplication doesn't have that and the integer overflow could lead to an out of bounds access. Fixes: a292fdecd728 ("drm/amdgpu: Implement userqueue signal/wait IOCTL") Signed-off-by: Dan Carpenter Signed-off-by: Alex Deucher --- diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c index fc4d0d42e2238..a86616c6deeff 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c @@ -430,7 +430,7 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, void *data, num_syncobj_handles = args->num_syncobj_handles; syncobj_handles = memdup_user(u64_to_user_ptr(args->syncobj_handles), - sizeof(u32) * num_syncobj_handles); + size_mul(sizeof(u32), num_syncobj_handles)); if (IS_ERR(syncobj_handles)) return PTR_ERR(syncobj_handles); @@ -612,13 +612,13 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data, num_read_bo_handles = wait_info->num_bo_read_handles; bo_handles_read = memdup_user(u64_to_user_ptr(wait_info->bo_read_handles), - sizeof(u32) * num_read_bo_handles); + size_mul(sizeof(u32), num_read_bo_handles)); if (IS_ERR(bo_handles_read)) return PTR_ERR(bo_handles_read); num_write_bo_handles = wait_info->num_bo_write_handles; bo_handles_write = memdup_user(u64_to_user_ptr(wait_info->bo_write_handles), - sizeof(u32) * num_write_bo_handles); + size_mul(sizeof(u32), num_write_bo_handles)); if (IS_ERR(bo_handles_write)) { r = PTR_ERR(bo_handles_write); goto free_bo_handles_read; @@ -626,7 +626,7 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data, num_syncobj = wait_info->num_syncobj_handles; syncobj_handles = memdup_user(u64_to_user_ptr(wait_info->syncobj_handles), - sizeof(u32) * num_syncobj); + size_mul(sizeof(u32), num_syncobj)); if (IS_ERR(syncobj_handles)) { r = PTR_ERR(syncobj_handles); goto free_bo_handles_write;