summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPrasad Sodagudi <psodagud@codeaurora.org>2015-03-25 09:45:07 +0530
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:04:29 -0700
commit85f869dd57f2df41462a9439cfa2eeed2f164dba (patch)
tree6e7f04df3bbae470e08b97c595b00f39cd367f4e
parent114a9f67b6466c43cc2ebb8a97eea94b3d87086a (diff)
ion: validate ion client in ion_debug_client_show() and extract data
ion client can get created and destroyed dynamically. Client data struct may not be in proper state if one core is reading client information and other core is destroying the same client. There is no synchronization between ion_debug_client_show() and ion_client_destroy(), that leaves client data structures in uncertain state and which may lead to system crash. So add a check in ion_debug_client_show(), to verify whether the client is part of ion device rb tree or not before retrieving client data. CRs-Fixed: 743714 Change-Id: Ic4c2f9dff905d9bb8fbf2e56b7c6396dc01bdf8f Signed-off-by: Prasad Sodagudi <psodagud@codeaurora.org>
-rw-r--r--drivers/staging/android/ion/ion.c29
1 files changed, 28 insertions, 1 deletions
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index 9648d0ccf0b2..e5cf8da9763d 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -119,6 +119,8 @@ struct ion_handle {
int id;
};
+static struct ion_device *ion_dev;
+
bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer)
{
return (buffer->flags & ION_FLAG_CACHED) &&
@@ -733,7 +735,30 @@ EXPORT_SYMBOL(ion_unmap_kernel);
static int ion_debug_client_show(struct seq_file *s, void *unused)
{
struct ion_client *client = s->private;
- struct rb_node *n;
+ struct rb_node *n, *cnode;
+ bool found = false;
+
+ down_write(&ion_dev->lock);
+
+ if (!client || (client->dev != ion_dev)) {
+ up_write(&ion_dev->lock);
+ return -EINVAL;
+ }
+
+ cnode = rb_first(&ion_dev->clients);
+ for ( ; cnode; cnode = rb_next(cnode)) {
+ struct ion_client *c = rb_entry(cnode,
+ struct ion_client, node);
+ if (client == c) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ up_write(&ion_dev->lock);
+ return -EINVAL;
+ }
seq_printf(s, "%16.16s: %16.16s : %16.16s : %12.12s\n",
"heap_name", "size_in_bytes", "handle refcount",
@@ -753,6 +778,7 @@ static int ion_debug_client_show(struct seq_file *s, void *unused)
seq_printf(s, "\n");
}
mutex_unlock(&client->lock);
+ up_write(&ion_dev->lock);
return 0;
}
@@ -1936,6 +1962,7 @@ debugfs_done:
init_rwsem(&idev->lock);
plist_head_init(&idev->heaps);
idev->clients = RB_ROOT;
+ ion_dev = idev;
return idev;
}
EXPORT_SYMBOL(ion_device_create);