diff options
| author | Prasad Sodagudi <psodagud@codeaurora.org> | 2015-03-25 09:45:07 +0530 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-22 11:04:29 -0700 |
| commit | 85f869dd57f2df41462a9439cfa2eeed2f164dba (patch) | |
| tree | 6e7f04df3bbae470e08b97c595b00f39cd367f4e | |
| parent | 114a9f67b6466c43cc2ebb8a97eea94b3d87086a (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.c | 29 |
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); |
