On 2/20/26 09:28, Sunil Khatri wrote:
> There are various input arguments set by user in the signal/wait
> ioctl which could be a huge value eventually leading to a OOM
> condition and system crash and could be exploited.
> 
> So check these input value against AMDGPU_USERQ_MAX_HANDLES
> which is big enough value and also to avoid out of memory
> condition.
> 
> Signed-off-by: Sunil Khatri <[email protected]>
> ---
>  .../gpu/drm/amd/amdgpu/amdgpu_userq_fence.c   | 37 +++++++++++++++++++
>  1 file changed, 37 insertions(+)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
> index a6eb703b62c4..b9810313c5ab 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
> @@ -35,6 +35,8 @@
>  static const struct dma_fence_ops amdgpu_userq_fence_ops;
>  static struct kmem_cache *amdgpu_userq_fence_slab;
>  
> +#define AMDGPU_USERQ_MAX_HANDLES     (1U << 16)
> +
>  int amdgpu_userq_fence_slab_init(void)
>  {
>       amdgpu_userq_fence_slab = kmem_cache_create("amdgpu_userq_fence",
> @@ -480,6 +482,9 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, 
> void *data,
>               return -ENOTSUPP;
>  
>       num_syncobj_handles = args->num_syncobj_handles;
> +     if (num_syncobj_handles > AMDGPU_USERQ_MAX_HANDLES)
> +             return -EINVAL;
> +
>       syncobj_handles = 
> memdup_array_user(u64_to_user_ptr(args->syncobj_handles),
>                                           num_syncobj_handles, sizeof(u32));

There is actually the helper function drm_syncobj_array_find() which should 
handle all of that.

If it doesn't we need to improve that function.

>       if (IS_ERR(syncobj_handles))
> @@ -501,6 +506,11 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, 
> void *data,
>       }
>  
>       num_read_bo_handles = args->num_bo_read_handles;
> +     if (num_read_bo_handles > AMDGPU_USERQ_MAX_HANDLES) {
> +             r = -EINVAL;
> +             goto free_syncobj;
> +     }
> +

Same here, we already have a helper for that. I started using those helpers in 
my patch.

Maybe just extract that change and apply it separately.

Regards,
Christian.

>       bo_handles_read = 
> memdup_array_user(u64_to_user_ptr(args->bo_read_handles),
>                                           num_read_bo_handles, sizeof(u32));
>       if (IS_ERR(bo_handles_read)) {
> @@ -524,6 +534,11 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, 
> void *data,
>       }
>  
>       num_write_bo_handles = args->num_bo_write_handles;
> +     if (num_write_bo_handles > AMDGPU_USERQ_MAX_HANDLES) {
> +             r = -EINVAL;
> +             goto put_gobj_read;
> +     }
> +
>       bo_handles_write = 
> memdup_array_user(u64_to_user_ptr(args->bo_write_handles),
>                                            num_write_bo_handles, sizeof(u32));
>       if (IS_ERR(bo_handles_write)) {
> @@ -666,12 +681,20 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, 
> void *data,
>               return -ENOTSUPP;
>  
>       num_read_bo_handles = wait_info->num_bo_read_handles;
> +     if (num_read_bo_handles > AMDGPU_USERQ_MAX_HANDLES)
> +             return -EINVAL;
> +
>       bo_handles_read = 
> memdup_array_user(u64_to_user_ptr(wait_info->bo_read_handles),
>                                           num_read_bo_handles, sizeof(u32));
>       if (IS_ERR(bo_handles_read))
>               return PTR_ERR(bo_handles_read);
>  
>       num_write_bo_handles = wait_info->num_bo_write_handles;
> +     if (num_write_bo_handles > AMDGPU_USERQ_MAX_HANDLES) {
> +             r = -EINVAL;
> +             goto free_bo_handles_read;
> +     }
> +
>       bo_handles_write = 
> memdup_array_user(u64_to_user_ptr(wait_info->bo_write_handles),
>                                            num_write_bo_handles, sizeof(u32));
>       if (IS_ERR(bo_handles_write)) {
> @@ -680,6 +703,11 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void 
> *data,
>       }
>  
>       num_syncobj = wait_info->num_syncobj_handles;
> +     if (num_syncobj > AMDGPU_USERQ_MAX_HANDLES) {
> +             r = -EINVAL;
> +             goto free_bo_handles_write;
> +     }
> +
>       syncobj_handles = 
> memdup_array_user(u64_to_user_ptr(wait_info->syncobj_handles),
>                                           num_syncobj, sizeof(u32));
>       if (IS_ERR(syncobj_handles)) {
> @@ -688,6 +716,10 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void 
> *data,
>       }
>  
>       num_points = wait_info->num_syncobj_timeline_handles;
> +     if (num_points > AMDGPU_USERQ_MAX_HANDLES) {
> +             r = -EINVAL;
> +             goto free_syncobj_handles;
> +     }
>       timeline_handles = 
> memdup_array_user(u64_to_user_ptr(wait_info->syncobj_timeline_handles),
>                                            num_points, sizeof(u32));
>       if (IS_ERR(timeline_handles)) {
> @@ -750,6 +782,11 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void 
> *data,
>               }
>       }
>  
> +     if (wait_info->num_fences > AMDGPU_USERQ_MAX_HANDLES) {
> +             r = -EINVAL;
> +             goto exec_fini;
> +     }
> +
>       if (!wait_info->num_fences) {
>               if (num_points) {
>                       struct dma_fence_unwrap iter;

Reply via email to