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

Reply via email to