diff options
author | Tuomas Tynkkynen <ttynkkynen@nvidia.com> | 2012-07-31 15:01:04 +0300 |
---|---|---|
committer | Simone Willett <swillett@nvidia.com> | 2012-08-10 23:15:03 -0700 |
commit | 70d4ced2d12a1251202d67ffae7f5c0b3013cc94 (patch) | |
tree | 34a76e46b9be21b6f785073600d9a5df0d427e2e | |
parent | 642d37a0eee196d0ce811dd11bb7af5ba281ee3a (diff) |
video: tegra: nvmap: fix usermode input validation
nvmap_pin_ids accepts a list of handles to pin, which are passed
directly from usermode when called from nvmap_ioctl_pinop.
However, if invalid handles are passed in, the function might
still access them as valid handles, and cause a crash.
Bug 1023954
Change-Id: I6b98a2ef448bb496be7d569ddd4fb516fc399cba
Signed-off-by: Tuomas Tynkkynen <ttynkkynen@nvidia.com>
Reviewed-on: http://git-master/r/119667
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Juha Tukkinen <jtukkinen@nvidia.com>
-rw-r--r-- | drivers/video/tegra/nvmap/nvmap.c | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/drivers/video/tegra/nvmap/nvmap.c b/drivers/video/tegra/nvmap/nvmap.c index b7fd695d04ee..a0dcf26337f8 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-2011, NVIDIA Corporation. + * Copyright (c) 2009-2012, NVIDIA Corporation. * * 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 @@ -271,7 +271,7 @@ int nvmap_pin_ids(struct nvmap_client *client, * if the caller crashes after pinning a global handle, the handle * will be permanently leaked. */ nvmap_ref_lock(client); - for (i = 0; i < nr && !ret; i++) { + for (i = 0; i < nr; i++) { ref = _nvmap_validate_id_locked(client, ids[i]); if (ref) { atomic_inc(&ref->pin); @@ -280,19 +280,19 @@ int nvmap_pin_ids(struct nvmap_client *client, struct nvmap_handle *verify; nvmap_ref_unlock(client); verify = nvmap_validate_get(client, ids[i]); - if (verify) + if (verify) { nvmap_warn(client, "%s pinning unreferenced " "handle %p\n", current->group_leader->comm, h[i]); - else + } else { + h[i] = NULL; ret = -EPERM; + } nvmap_ref_lock(client); } } nvmap_ref_unlock(client); - nr = i; - if (ret) goto out; @@ -317,6 +317,9 @@ out: if (ret) { nvmap_ref_lock(client); for (i = 0; i < nr; i++) { + if(!ids[i]) + continue; + ref = _nvmap_validate_id_locked(client, ids[i]); if (!ref) { nvmap_warn(client, "%s freed handle %p " @@ -330,7 +333,8 @@ out: nvmap_ref_unlock(client); for (i = 0; i < nr; i++) - nvmap_handle_put(h[i]); + if(h[i]) + nvmap_handle_put(h[i]); } return ret; |