[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.

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