UDMABUF_CREATE_LIST copies an array whose element count comes from
userspace. The count is bounded by the list_limit module parameter, but
that parameter does not need negative values.

Make list_limit unsigned so its type matches the u32 count field. Also
use memdup_array_user() for the list copy so the element-count
multiplication is checked before allocation and copying.

Suggested-by: Christian König <[email protected]>
Signed-off-by: Yousef Alhouseen <[email protected]>
---
Changes in v2:
- Make list_limit unsigned as suggested by Christian.
- Keep the checked array copy and drop the local u32 byte-count temporary.

 drivers/dma-buf/udmabuf.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c
index bced421c0..e34a3b135 100644
--- a/drivers/dma-buf/udmabuf.c
+++ b/drivers/dma-buf/udmabuf.c
@@ -21,8 +21,8 @@
 #include <linux/udmabuf.h>
 #include <linux/vmalloc.h>

-static int list_limit = 1024;
-module_param(list_limit, int, 0644);
+static unsigned int list_limit = 1024;
+module_param(list_limit, uint, 0644);
 MODULE_PARM_DESC(list_limit, "udmabuf_create_list->count limit.
Default is 1024.");
 static int size_limit_mb = 64;
 module_param(size_limit_mb, int, 0644);
@@ -471,12 +471,11 @@ static long udmabuf_ioctl_create_list(struct
file *filp, unsigned long arg)
        struct udmabuf_create_list head;
        struct udmabuf_create_item *list;
        int ret = -EINVAL;
-       u32 lsize;

        if (copy_from_user(&head, (void __user *)arg, sizeof(head)))
                return -EFAULT;
        if (head.count > list_limit)
                return -EINVAL;
-       lsize = sizeof(struct udmabuf_create_item) * head.count;
-       list = memdup_user((void __user *)(arg + sizeof(head)), lsize);
+       list = memdup_array_user((void __user *)(arg + sizeof(head)),
+                                     head.count, sizeof(*list));
        if (IS_ERR(list))
                return PTR_ERR(list);

-- 
2.54.0

Reply via email to