On 3/12/26 09:33, Zhang, Jesse(Jie) wrote: > [AMD Official Use Only - AMD Internal Distribution Only] > >> -----Original Message----- >> From: Koenig, Christian <[email protected]> >> Sent: Thursday, March 12, 2026 4:23 PM >> To: Zhang, Jesse(Jie) <[email protected]>; [email protected] >> Cc: Deucher, Alexander <[email protected]> >> Subject: Re: [PATCH] drm/amdgpu: add overflow check for BO list array >> allocation >> >> On 3/12/26 09:18, Jesse.Zhang wrote: >>> When allocating memory for a BO list array, the multiplication >>> bo_number * info_size may overflow on 32-bit systems if userspace >>> supplies large values. This could lead to allocating a smaller buffer >>> than expected, followed by a memset or copy_from_user that writes >>> beyond the allocated memory, potentially causing memory corruption or >>> information disclosure. >>> >>> Add an overflow check using check_mul_overflow to detect such cases. >>> Also ensure the resulting allocation size does not exceed INT_MAX, as >>> the subsequent user copy operations may rely on this limit. >>> Return -EINVAL if either condition fails. >> >> That is completely unnecessary, vmemdup_array_user() already does that check. >> >>> >>> A crash log illustrating the issue: >>> >>> [ 2943.053706] RIP: 0010:__kvmalloc_node_noprof+0x5be/0x8a0 >>> ... >>> [ 2943.053725] Call Trace: >>> [ 2943.053728] amdgpu_bo_create_list_entry_array+0x42/0x130 [amdgpu] [ >>> 2943.053947] amdgpu_bo_list_ioctl+0x51/0x300 [amdgpu] [ 2943.054277] >>> drm_ioctl+0x2cb/0x5a0 [drm] [ 2943.054379] __x64_sys_ioctl+0x9e/0xf0 >>> >>> The overflow occurs in the allocation inside >>> amdgpu_bo_create_list_entry_array, leading to a crash in vmemdup_user >>> (via __kvmalloc_node_noprof). >> >> How and on which kernel can you reproduce that? > We are developing some fuzz tests for the unified project. > The tests involve passing different levels of garbage data and ensuring the > kernel can handle this data correctly. > This issue can be reproduced on the amd-staging-drm-next branch.
Do you have the full backtrace? Regards, Christian. > > Thanks > Jesse >> >> Regards, >> Christian. >> >>> >>> Signed-off-by: Jesse.Zhang <[email protected]> >>> --- >>> drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c | 8 +++++++- >>> 1 file changed, 7 insertions(+), 1 deletion(-) >>> >>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c >>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c >>> index 87ec46c56a6e..efab39ba7f51 100644 >>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c >>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c >>> @@ -29,6 +29,7 @@ >>> */ >>> >>> #include <linux/sort.h> >>> +#include <linux/overflow.h> >>> #include <linux/uaccess.h> >>> >>> #include "amdgpu.h" >>> @@ -187,6 +188,11 @@ int amdgpu_bo_create_list_entry_array(struct >> drm_amdgpu_bo_list_in *in, >>> const uint32_t bo_info_size = in->bo_info_size; >>> const uint32_t bo_number = in->bo_number; >>> struct drm_amdgpu_bo_list_entry *info; >>> + size_t alloc_size; >>> + >>> + if (check_mul_overflow((size_t)bo_number, (size_t)info_size, >>> + &alloc_size) || alloc_size > INT_MAX) >>> + return -EINVAL; >>> >>> /* copy the handle array from userspace to a kernel buffer */ >>> if (likely(info_size == bo_info_size)) { @@ -201,7 +207,7 @@ int >>> amdgpu_bo_create_list_entry_array(struct drm_amdgpu_bo_list_in *in, >>> if (!info) >>> return -ENOMEM; >>> >>> - memset(info, 0, bo_number * info_size); >>> + memset(info, 0, alloc_size); >>> for (i = 0; i < bo_number; ++i, uptr += bo_info_size) { >>> if (copy_from_user(&info[i], uptr, bytes)) { >>> kvfree(info); >
