summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary King <gking@nvidia.com>2010-03-05 10:41:32 -0800
committerGary King <gking@nvidia.com>2010-03-05 11:04:19 -0800
commite017a62d01aa6c7d0253b15182669295f000fa03 (patch)
tree19dc51fc6ce24c578f0bc9a8a3bf995428ea731f
parentded58bd5f0cab2bc6e4f0f5435422b6c0c23f6be (diff)
[nvmap] handle NULL return for pin multiple, fix infinite loop
the handle alignment parameter query had an off-by-one bug in its loop initializer which caused any carveout handle to trigger an infinite loop. the only caller of this API was the debug EGL driver, which used it to verify that the allocation matched the requested alignment. also, if the user passes NULL as the address array when pinning multiple handles to ioctl_pinop, pin the handles and skip the output write, rather than returning a permission error. big thanks to antti for finding the infinite loop. bug 660526 Change-Id: I90f819a231b5a8bef5b473252122cdbefc744efb Reviewed-on: http://git-master/r/782 Reviewed-by: Gary King <gking@nvidia.com> Tested-by: Gary King <gking@nvidia.com>
-rw-r--r--drivers/char/nvmap.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/drivers/char/nvmap.c b/drivers/char/nvmap.c
index 8546061016b6..c7f1cc44c5b6 100644
--- a/drivers/char/nvmap.c
+++ b/drivers/char/nvmap.c
@@ -1630,7 +1630,8 @@ static int nvmap_ioctl_pinop(struct file *filp,
size_t bytes = op.count * sizeof(unsigned long *);
if (!access_ok(VERIFY_READ, (void *)op.handles, bytes))
return -EPERM;
- if (is_pin && !access_ok(VERIFY_WRITE, (void *)op.addr, bytes))
+ if (is_pin && op.addr &&
+ !access_ok(VERIFY_WRITE, (void *)op.addr, bytes))
return -EPERM;
if (op.count <= ARRAY_SIZE(on_stack)) refs = on_stack;
@@ -1662,6 +1663,8 @@ static int nvmap_ioctl_pinop(struct file *filp,
output = (unsigned long __user *)&(tmp->addr);
}
+ if (!output) goto out;
+
for (i=0; i<op.count; i++) {
unsigned long addr;
h = (struct nvmap_handle *)refs[i];
@@ -2479,15 +2482,15 @@ static unsigned int _nvmap_do_get_param(struct nvmap_handle *h,
return h->orig_size;
else if (param==NVMEM_HANDLE_PARAM_ALIGNMENT) {
- unsigned int i = 0;
-
if (!h->alloc) return 0;
if (h->heap_pgalloc) return PAGE_SIZE;
else {
+ unsigned int i=1;
+ if (!h->carveout.base) return SZ_4M;
while (!(i & h->carveout.base)) i<<=1;
+ return i;
}
- return i;
} else if (param==NVMEM_HANDLE_PARAM_BASE) {
WARN_ON(!h->alloc || !atomic_read(&h->pin));