summaryrefslogtreecommitdiff
path: root/drivers/video/tegra/nvmap/nvmap_ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/tegra/nvmap/nvmap_ioctl.c')
-rw-r--r--drivers/video/tegra/nvmap/nvmap_ioctl.c90
1 files changed, 46 insertions, 44 deletions
diff --git a/drivers/video/tegra/nvmap/nvmap_ioctl.c b/drivers/video/tegra/nvmap/nvmap_ioctl.c
index 850afd1ff437..3f7573a9ffcc 100644
--- a/drivers/video/tegra/nvmap/nvmap_ioctl.c
+++ b/drivers/video/tegra/nvmap/nvmap_ioctl.c
@@ -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
@@ -88,6 +88,7 @@ int nvmap_ioctl_pinop(struct file *filp, bool is_pin, void __user *arg,
return -EFAULT;
op.handles = (__u32 *)(uintptr_t)op32.handles;
op.count = op32.count;
+ op.addr = (unsigned long *)(uintptr_t)op32.addr;
} else
#endif
if (copy_from_user(&op, arg, sizeof(op)))
@@ -226,6 +227,33 @@ const struct file_operations nvmap_fd_fops = {
.mmap = nvmap_share_mmap,
};
+static int nvmap_install_fd(struct nvmap_client *client,
+ struct nvmap_handle *handle, int fd, void __user *arg,
+ void *op, size_t op_size, bool free)
+{
+ int err = 0;
+
+ if (IS_ERR_VALUE(fd)) {
+ err = fd;
+ goto fd_fail;
+ }
+
+ if (copy_to_user(arg, op, op_size)) {
+ err = -EFAULT;
+ goto copy_fail;
+ }
+
+ fd_install(fd, handle->dmabuf->file);
+ return err;
+
+copy_fail:
+ put_unused_fd(fd);
+fd_fail:
+ if (free)
+ nvmap_free_handle(client, handle);
+ return err;
+}
+
int nvmap_ioctl_getfd(struct file *filp, void __user *arg)
{
struct nvmap_handle *handle;
@@ -241,14 +269,9 @@ int nvmap_ioctl_getfd(struct file *filp, void __user *arg)
op.fd = nvmap_get_dmabuf_fd(client, handle);
nvmap_handle_put(handle);
- if (op.fd < 0)
- return op.fd;
- if (copy_to_user(arg, &op, sizeof(op))) {
- sys_close(op.fd);
- return -EFAULT;
- }
- return 0;
+ return nvmap_install_fd(client, handle,
+ op.fd, arg, &op, sizeof(op), 0);
}
int nvmap_ioctl_alloc(struct file *filp, void __user *arg)
@@ -309,30 +332,11 @@ int nvmap_ioctl_alloc_kind(struct file *filp, void __user *arg)
return err;
}
-int nvmap_create_fd(struct nvmap_client *client, struct nvmap_handle *h)
-{
- int fd;
-
- fd = __nvmap_dmabuf_fd(client, h->dmabuf, O_CLOEXEC);
- BUG_ON(fd == 0);
- if (fd < 0) {
- pr_err("Out of file descriptors");
- return fd;
- }
- /* __nvmap_dmabuf_fd() associates fd with dma_buf->file *.
- * fd close drops one ref count on dmabuf->file *.
- * to balance ref count, ref count dma_buf.
- */
- get_dma_buf(h->dmabuf);
- return fd;
-}
-
int nvmap_ioctl_create(struct file *filp, unsigned int cmd, void __user *arg)
{
struct nvmap_create_handle op;
struct nvmap_handle_ref *ref = NULL;
struct nvmap_client *client = filp->private_data;
- int err = 0;
int fd = 0;
if (copy_from_user(&op, arg, sizeof(op)))
@@ -354,20 +358,10 @@ int nvmap_ioctl_create(struct file *filp, unsigned int cmd, void __user *arg)
if (IS_ERR(ref))
return PTR_ERR(ref);
- fd = nvmap_create_fd(client, ref->handle);
- if (fd < 0)
- err = fd;
-
+ fd = nvmap_get_dmabuf_fd(client, ref->handle);
op.handle = fd;
-
- if (copy_to_user(arg, &op, sizeof(op))) {
- err = -EFAULT;
- nvmap_free_handle(client, __nvmap_ref_to_id(ref));
- }
-
- if (err && fd > 0)
- sys_close(fd);
- return err;
+ return nvmap_install_fd(client, ref->handle, fd,
+ arg, &op, sizeof(op), 1);
}
int nvmap_map_into_caller_ptr(struct file *filp, void __user *arg, bool is32)
@@ -472,9 +466,9 @@ int nvmap_ioctl_get_param(struct file *filp, void __user *arg, bool is32)
struct nvmap_handle_param __user *uarg = arg;
struct nvmap_handle_param op;
struct nvmap_client *client = filp->private_data;
- struct nvmap_handle_ref *ref;
- struct nvmap_handle *h;
- u64 result;
+ struct nvmap_handle_ref *ref = NULL;
+ struct nvmap_handle *h = NULL;
+ u64 result = 0;
int err = 0;
#ifdef CONFIG_COMPAT
@@ -500,6 +494,9 @@ int nvmap_ioctl_get_param(struct file *filp, void __user *arg, bool is32)
}
err = nvmap_get_handle_param(client, ref, op.param, &result);
+ if (err) {
+ goto ref_fail;
+ }
#ifdef CONFIG_COMPAT
if (is32)
@@ -936,6 +933,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 +1090,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)))