video: tegra: nvmap: fix time-of-check,time-of-use vulnerability
Sri Krishna chowdary [Fri, 10 Feb 2017 09:32:14 +0000 (14:32 +0530)]
Validate the region specified by offset and size before performing
the operations like nvmap_prot_handle, nvmap_cache_maint and nvmap_handle_mk*.

This validation of offset and size once the values are in local variables
guarantees that even though user space changes the values in user buffers,
nvmap continues to perform operations with the contents that are validated.

Fixes Google Bug 34113000.

bug 1862379

Change-Id: Ief81887b3d94b49f3dcf4d2680d9d7b257c54092
Signed-off-by: Sri Krishna chowdary <schowdary@nvidia.com>
Signed-off-by: Bibek Basu <bbasu@nvidia.com>
Reviewed-on: http://git-master/r/1298712
(cherry picked from commit f45441da608d8015ece73d253d4bdb48863f99e2)
Reviewed-on: http://git-master/r/1310316
(cherry picked from commit 57367ab3be5f1c52dd6b885f114ae90dfce5a363)
Reviewed-on: http://git-master/r/1319910
GVS: Gerrit_Virtual_Submit

drivers/video/tegra/nvmap/nvmap_ioctl.c
drivers/video/tegra/nvmap/nvmap_mm.c
drivers/video/tegra/nvmap/nvmap_priv.h

index 850afd1..7e59d24 100644 (file)
@@ -3,7 +3,7 @@
  *
  * User-space interface to nvmap
  *
- * Copyright (c) 2011-2014, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2011-2017, NVIDIA CORPORATION. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -936,6 +936,11 @@ int __nvmap_do_cache_maint(struct nvmap_client *client,
        if (!h)
                return -EFAULT;
 
+       if ((start >= h->size) || (end > h->size)) {
+               nvmap_handle_put(h);
+               return -EFAULT;
+       }
+
        if (op == NVMAP_CACHE_OP_INV)
                op = NVMAP_CACHE_OP_WB_INV;
 
@@ -1088,7 +1093,7 @@ int nvmap_ioctl_cache_maint_list(struct file *filp, void __user *arg,
        if (copy_from_user(&op, arg, sizeof(op)))
                return -EFAULT;
 
-       if (!op.nr)
+       if (!op.nr || op.nr > UINT_MAX / sizeof(u32))
                return -EINVAL;
 
        if (!access_ok(VERIFY_READ, op.handles, op.nr * sizeof(u32)))
index 133f00b..30994e6 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Some MM related functionality specific to nvmap.
  *
- * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2013-2017, NVIDIA CORPORATION. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -193,6 +193,10 @@ void nvmap_zap_handle(struct nvmap_handle *handle, u32 offset, u32 size)
 
        size = PAGE_ALIGN((offset & ~PAGE_MASK) + size);
 
+       if ((offset >= handle->size) || (offset > handle->size - size) ||
+           (size > handle->size))
+               return;
+
        mutex_lock(&handle->lock);
        vmas = &handle->vmas;
        list_for_each_entry(vma_list, vmas, list) {
index a90a326..7057457 100644 (file)
@@ -3,7 +3,7 @@
  *
  * GPU memory management driver for Tegra
  *
- * Copyright (c) 2009-2016, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2009-2017, NVIDIA CORPORATION. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -467,10 +467,13 @@ static inline void nvmap_handle_mk(struct nvmap_handle *h,
                                   void (*fn)(struct page **))
 {
        int i;
-       int start_page = PAGE_ALIGN(offset) >> PAGE_SHIFT;
-       int end_page = (offset + size) >> PAGE_SHIFT;
+       u32 start_page = offset >> PAGE_SHIFT;
+       u32 end_page = PAGE_ALIGN(offset + size) >> PAGE_SHIFT;
 
-       if (h->heap_pgalloc) {
+       if (h->heap_pgalloc &&
+               (offset < h->size) &&
+               (size <= h->size) &&
+               (offset <= (h->size - size))) {
                for (i = start_page; i < end_page; i++)
                        fn(&h->pgalloc.pages[i]);
        }