aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Rosenberg <drosen@google.com>2016-11-02 17:43:51 -0700
committerBen Fennema <fennema@google.com>2017-08-25 14:33:06 -0700
commit2e9efae734f949194a616bc9a08c71b2cd188997 (patch)
tree3ebcb75605f846336acf14b0e038209624a03fa6
parent0682eaefc21999ef7ba37bd96e9323879e55d9be (diff)
ion: Fix use after free during ION_IOC_ALLOCandroid-wear-o-preview-4_r0.1
If a user happens to call ION_IOC_FREE during an ION_IOC_ALLOC on the just allocated id, and the copy_to_user fails, the cleanup code will attempt to free an already freed handle. This adds a wrapper for ion_alloc that adds an ion_handle_get to avoid this. Bug: 31568617 Bug: 32987001 Change-Id: I476e5bd5372b5178a213f1fea143d270cf9361ed Signed-off-by: Daniel Rosenberg <drosen@google.com>
-rwxr-xr-xdrivers/staging/android/ion/ion.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index bdd0d95f1443..b30df008a9ef 100755
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -562,9 +562,9 @@ static int ion_handle_add(struct ion_client *client, struct ion_handle *handle)
return 0;
}
-struct ion_handle *ion_alloc(struct ion_client *client, size_t len,
+static struct ion_handle *__ion_alloc(struct ion_client *client, size_t len,
size_t align, unsigned int heap_id_mask,
- unsigned int flags)
+ unsigned int flags, bool grab_handle)
{
struct ion_handle *handle;
struct ion_device *dev = client->dev;
@@ -659,6 +659,8 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len,
return handle;
mutex_lock(&client->lock);
+ if (grab_handle)
+ ion_handle_get(handle);
ret = ion_handle_add(client, handle);
mutex_unlock(&client->lock);
if (ret) {
@@ -668,6 +670,13 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len,
return handle;
}
+
+struct ion_handle *ion_alloc(struct ion_client *client, size_t len,
+ size_t align, unsigned int heap_id_mask,
+ unsigned int flags)
+{
+ return __ion_alloc(client, len, align, heap_id_mask, flags, false);
+}
EXPORT_SYMBOL(ion_alloc);
@@ -1562,10 +1571,10 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct ion_handle *handle;
- handle = ion_alloc(client, data.allocation.len,
+ handle = __ion_alloc(client, data.allocation.len,
data.allocation.align,
data.allocation.heap_id_mask,
- data.allocation.flags);
+ data.allocation.flags, true);
if (IS_ERR(handle))
return PTR_ERR(handle);
pass_to_user(handle);
@@ -1656,6 +1665,8 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return -EFAULT;
}
}
+ if (cleanup_handle)
+ ion_handle_put(cleanup_handle);
return ret;
}