diff options
author | Sri Krishna chowdary <schowdary@nvidia.com> | 2016-12-14 11:58:30 +0530 |
---|---|---|
committer | Winnie Hsu <whsu@nvidia.com> | 2017-06-09 11:19:54 -0700 |
commit | b4328544835de3fc8215f37668dc97fc21013136 (patch) | |
tree | 774c63add5582421ff85f319088d20f88ea87888 /drivers | |
parent | 642ec539ddab846143db87673ace653d09c75e05 (diff) |
video: tegra: nvmap: Fix NULL pointer dereference
Consider the following case:
1. NVMAP_IOC_CREATE on IOVMM gives a valid fd to user space
2. user space does not call NVMAP_IOC_ALLOC.
3. user space calls a client driver IOCTL which calls dma_buf_map_attachment
4. call to dma_buf_map_attachment propagates till__nvmap_sg_table
which has heap_pgalloc as true and tries to access pages[]
which has all NULL.
5. Similarly, a dma_buf_kmap() can result in __nvmap_kmap() being called
which again results in NULL dereference if pages[] is accessed.
A valid __nvmap_sg_table should occur only when h->alloc is true.
So, add check for it.
bug 1838597
bug 1883708
Change-Id: I400d9d8a94ff1003db207fc9c252b9256d796f60
Signed-off-by: Sri Krishna chowdary <schowdary@nvidia.com>
Signed-off-by: Debarshi Dutta <ddutta@nvidia.com>
(cherry picked from commit 8244d104b7635cb0b26b651b6851498b9a84d7d6)
Reviewed-on: http://git-master/r/1489579
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
Tested-by: Bibek Basu <bbasu@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/tegra/nvmap/nvmap.c | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/drivers/video/tegra/nvmap/nvmap.c b/drivers/video/tegra/nvmap/nvmap.c index 09f436102c6b..662646a2d6c6 100644 --- a/drivers/video/tegra/nvmap/nvmap.c +++ b/drivers/video/tegra/nvmap/nvmap.c @@ -3,7 +3,7 @@ * * Memory manager for Tegra GPU * - * Copyright (c) 2009-2014, 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 @@ -196,6 +196,9 @@ void *__nvmap_kmap(struct nvmap_handle *h, unsigned int pagenum) if (!h) return NULL; + if (!h->alloc) + goto out; + if (pagenum >= h->size >> PAGE_SHIFT) goto out; prot = nvmap_pgprot(h, PG_PROT_KERNEL); @@ -222,7 +225,7 @@ void __nvmap_kunmap(struct nvmap_handle *h, unsigned int pagenum, phys_addr_t paddr; struct vm_struct *area = NULL; - if (!h || + if (!h || !h->alloc || WARN_ON(!virt_addr_valid(h)) || WARN_ON(!addr)) return; @@ -266,7 +269,7 @@ void *__nvmap_mmap(struct nvmap_handle *h) return NULL; if (!h->alloc) - return NULL; + goto put_handle; prot = nvmap_pgprot(h, PG_PROT_KERNEL); @@ -276,7 +279,7 @@ void *__nvmap_mmap(struct nvmap_handle *h) pages = nvmap_pages(h->pgalloc.pages, h->size >> PAGE_SHIFT); if (!pages) - return NULL; + goto put_handle; vaddr = vm_map_ram(pages, h->size >> PAGE_SHIFT, -1, prot); nvmap_altfree(pages, @@ -296,10 +299,8 @@ void *__nvmap_mmap(struct nvmap_handle *h) adj_size = PAGE_ALIGN(adj_size); v = alloc_vm_area(adj_size, 0); - if (!v) { - nvmap_handle_put(h); - return NULL; - } + if (!v) + goto put_handle; p = v->addr + (h->carveout->base & ~PAGE_MASK); ioremap_page_range((ulong)v->addr, (ulong)v->addr + adj_size, @@ -309,11 +310,14 @@ void *__nvmap_mmap(struct nvmap_handle *h) * the handle will not be freed while the kernel mapping exists. * nvmap_handle_put will be called by unmapping this address */ return p; +put_handle: + nvmap_handle_put(h); + return NULL; } void __nvmap_munmap(struct nvmap_handle *h, void *addr) { - if (!h || + if (!h || !h->alloc || WARN_ON(!virt_addr_valid(h)) || WARN_ON(!addr)) return; @@ -447,6 +451,11 @@ struct sg_table *__nvmap_sg_table(struct nvmap_client *client, if (!h) return ERR_PTR(-EINVAL); + if (!h->alloc) { + err = -EINVAL; + goto put_handle; + } + npages = PAGE_ALIGN(h->size) >> PAGE_SHIFT; sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); if (!sgt) { @@ -476,6 +485,7 @@ struct sg_table *__nvmap_sg_table(struct nvmap_client *client, err: kfree(sgt); +put_handle: nvmap_handle_put(h); return ERR_PTR(err); } |