OSDN Git Service

media: v4l2-ioctl: Use larger on-stack video copy buffers
authorSultan Alsawaf <sultan@kerneltoast.com>
Wed, 31 Jul 2019 06:53:13 +0000 (23:53 -0700)
committer0ranko0P <ranko0p@outlook.com>
Sat, 7 Dec 2019 10:22:18 +0000 (18:22 +0800)
We have a 16 KiB stack; buffers of 4 KiB and 512 B work perfectly fine
in place of a small 128-byte buffer and especially no on-stack buffer at
all. This avoids dynamic memory allocation more often, improving
performance, and it's safe according to stack usage measurements at
runtime.

Signed-off-by: Sultan Alsawaf <sultan@kerneltoast.com>
drivers/media/v4l2-core/v4l2-ioctl.c

index fe34b3c..ebef7e0 100644 (file)
@@ -2803,7 +2803,8 @@ long
 video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
               v4l2_kioctl func)
 {
-       char    sbuf[128];
+       char    mbuf_onstack[SZ_512] __aligned(sizeof(long));
+       char    sbuf[SZ_4K] __aligned(sizeof(long));
        void    *mbuf = NULL;
        void    *parg = (void *)arg;
        long    err  = -EINVAL;
@@ -2865,10 +2866,14 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
                 * array) fits into sbuf (so that mbuf will still remain
                 * unused up to here).
                 */
-               mbuf = kmalloc(array_size, GFP_KERNEL);
-               err = -ENOMEM;
-               if (NULL == mbuf)
-                       goto out_array_args;
+               if (array_size <= ARRAY_SIZE(mbuf_onstack)) {
+                       mbuf = mbuf_onstack;
+               } else {
+                       mbuf = kmalloc(array_size, GFP_KERNEL);
+                       err = -ENOMEM;
+                       if (NULL == mbuf)
+                               goto out_array_args;
+               }
                err = -EFAULT;
                if (copy_from_user(mbuf, user_ptr, array_size))
                        goto out_array_args;
@@ -2911,7 +2916,8 @@ out_array_args:
        }
 
 out:
-       kfree(mbuf);
+       if (mbuf != mbuf_onstack)
+               kfree(mbuf);
        return err;
 }
 EXPORT_SYMBOL(video_usercopy);