video: tegra: nvmap: Fix two integer overflows.
Tuomas Tynkkynen [Mon, 30 Jul 2012 09:40:45 +0000 (12:40 +0300)]
nvmap_ioctl_pinop kmalloc's a temporary buffer, whose length is directly
given by ioctl parameter from usermode. The total size of the buffer
is not checked for overflow, which will cause a kernel panic with some
inputs.

Also, a sizeof() is applied to wrong type when calculating the amount
of bytes to copy from userspace.

nvmap_map_into_caller_ptr attempts to validate that the memory range
to be mapped is correct, but integer overflow can cause the check to
fail. This will lead to mapping wrong pages from the allocated
handle later on, when the page fault handler gets called.

Bug 1025502

Change-Id: I71a09c40c209dba9c5b37c3912e92a81e6f87e80
Signed-off-by: Tuomas Tynkkynen <ttynkkynen@nvidia.com>

drivers/video/tegra/nvmap/nvmap_ioctl.c

index 44f00d2..5bfbbf6 100644 (file)
@@ -65,10 +65,10 @@ int nvmap_ioctl_pinop(struct file *filp, bool is_pin, void __user *arg)
                return -EINVAL;
 
        if (op.count > 1) {
-               size_t bytes = op.count * sizeof(unsigned long *);
+               size_t bytes = op.count * sizeof(*refs); /* kcalloc below will catch overflow. */
 
                if (op.count > ARRAY_SIZE(on_stack))
-                       refs = kmalloc(op.count * sizeof(*refs), GFP_KERNEL);
+                       refs = kcalloc(op.count, sizeof(*refs), GFP_KERNEL);
                else
                        refs = on_stack;
 
@@ -251,7 +251,7 @@ int nvmap_map_into_caller_ptr(struct file *filp, void __user *arg)
                goto out;
        }
 
-       if ((op.offset + op.length) > h->size) {
+       if (op.offset > h->size || (op.offset + op.length) > h->size) {
                err = -EADDRNOTAVAIL;
                goto out;
        }