Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b4b8ec19 authored by Daniel Rosenberg's avatar Daniel Rosenberg Committed by Dennis Cagle
Browse files

ANDROID: ion: check for kref overflow



Userspace can cause the kref to handles to increment
arbitrarily high. Ensure it does not overflow.

Signed-off-by: default avatarDaniel Rosenberg <drosen@google.com>

Bug: 31992382
Test: See bug for poc
Change-Id: I6bff1df385742b1d836d43180dc87fadcea80782
Git-repo: https://android.googlesource.com/kernel/msm


Git-commit: 0c702db4d90de88df11057bcf0d8fb2dfe741605
Signed-off-by: default avatarDennis Cagle <d-cagle@codeaurora.org>
parent f90af475
Loading
Loading
Loading
Loading
+13 −3
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
 *
 */

#include <linux/atomic.h>
#include <linux/err.h>
#include <linux/file.h>
#include <linux/freezer.h>
@@ -406,6 +407,15 @@ static void ion_handle_get(struct ion_handle *handle)
	kref_get(&handle->ref);
}

/* Must hold the client lock */
static struct ion_handle* ion_handle_get_check_overflow(struct ion_handle *handle)
{
	if (atomic_read(&handle->ref.refcount) + 1 == 0)
		return ERR_PTR(-EOVERFLOW);
	ion_handle_get(handle);
	return handle;
}

static int ion_handle_put_nolock(struct ion_handle *handle)
{
	int ret;
@@ -452,9 +462,9 @@ static struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client,

	handle = idr_find(&client->idr, id);
	if (handle)
		ion_handle_get(handle);
		return ion_handle_get_check_overflow(handle);

	return handle ? handle : ERR_PTR(-EINVAL);
	return ERR_PTR(-EINVAL);
}

struct ion_handle *ion_handle_get_by_id(struct ion_client *client,
@@ -1407,7 +1417,7 @@ struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd)
	/* if a handle exists for this buffer just take a reference to it */
	handle = ion_handle_lookup(client, buffer);
	if (!IS_ERR(handle)) {
		ion_handle_get(handle);
		handle = ion_handle_get_check_overflow(handle);
		mutex_unlock(&client->lock);
		goto end;
	}