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);
> 

Reply via email to