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

Commit 6186c322 authored by Swetha Chikkaboraiah's avatar Swetha Chikkaboraiah Committed by Gerrit - the friendly Code Review server
Browse files

Subject: staging: android: ion: fix ION_IOC_{MAP,SHARE} use-after-free



This patch is 4.9.y only.  Kernels 4.12 and later are unaffected, since
all the underlying ion_handle infrastructure has been ripped out.

The ION_IOC_{MAP,SHARE} ioctls drop and reacquire client->lock several
times while operating on one of the client's ion_handles.  This creates
windows where userspace can call ION_IOC_FREE on the same client with
the same handle, and effectively make the kernel drop its own reference.
For example:

- thread A: ION_IOC_ALLOC creates an ion_handle with refcount 1
- thread A: starts ION_IOC_MAP and increments the refcount to 2
- thread B: ION_IOC_FREE decrements the refcount to 1
- thread B: ION_IOC_FREE decrements the refcount to 0 and frees the
            handle
- thread A: continues ION_IOC_MAP with a dangling ion_handle * to
            freed memory

Fix this by holding client->lock for the duration of
ION_IOC_{MAP,SHARE}, preventing the concurrent ION_IOC_FREE.  Also
remove ion_handle_get_by_id(), since there's literally no way to use it
safely.

Change-Id: If143504a6fa15ff96cf7e8577344996a133d9e17
Cc: stable@vger.kernel.org # v4.11-
Signed-off-by: default avatarGreg Hackmann <ghackmann@google.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Git-commit: 3fedc0cd
Git-repo: https://android.googlesource.com/kernel/common/


[schikk@codeaurora.org: fix trivial merge conflicts]
Signed-off-by: default avatarSwetha Chikkaboraiah <schikk@codeaurora.org>
parent 8d5672d7
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@
 * drivers/staging/android/ion/ion.c
 *
 * Copyright (C) 2011 Google, Inc.
 * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2011-2018, 2020, The Linux Foundation. All rights reserved.
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
@@ -1659,11 +1659,15 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
	{
		struct ion_handle *handle;

		mutex_lock(&client->lock);
		handle = ion_handle_get_by_id_nolock(client, data.handle.handle);
		if (IS_ERR(handle))
		if (IS_ERR(handle)) {
			mutex_unlock(&client->lock);
			return PTR_ERR(handle);
		data.fd.fd = ion_share_dma_buf_fd(client, handle);
		ion_handle_put(handle);
		}
		data.fd.fd = ion_share_dma_buf_fd_nolock(client, handle);
		ion_handle_put_nolock(handle);
		mutex_unlock(&client->lock);
		if (data.fd.fd < 0)
			ret = data.fd.fd;
		break;