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)); 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; + } + 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; -- 2.34.1
