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;