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

Commit b1232b02 authored by Marco Ballesio's avatar Marco Ballesio Committed by Li Li
Browse files

FROMGIT: binder: BINDER_GET_FROZEN_INFO ioctl

User space needs to know if binder transactions occurred to frozen
processes. Introduce a new BINDER_GET_FROZEN ioctl and keep track of
transactions occurring to frozen proceses.

Bug: 180989544
(cherry picked from commit c55019c24b22d6770bd8e2f12fbddf3f83d37547
 git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git

 char-misc-testing)
Signed-off-by: default avatarMarco Ballesio <balejs@google.com>
Signed-off-by: default avatarLi Li <dualli@google.com>
Acked-by: default avatarTodd Kjos <tkjos@google.com>
Link: https://lore.kernel.org/r/20210316011630.1121213-4-dualli@chromium.org


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Change-Id: Ie631f331ba4ca94a3bcdd43dec25fe9ba1306af2
parent a02d0f68
Loading
Loading
Loading
Loading
+55 −0
Original line number Diff line number Diff line
@@ -2496,6 +2496,10 @@ static int binder_proc_transaction(struct binder_transaction *t,
	}

	binder_inner_proc_lock(proc);
	if (proc->is_frozen) {
		proc->sync_recv |= !oneway;
		proc->async_recv |= oneway;
	}

	if ((proc->is_frozen && !oneway) || proc->is_dead ||
			(thread && thread->is_dead)) {
@@ -4776,6 +4780,8 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info,

	if (!info->enable) {
		binder_inner_proc_lock(target_proc);
		target_proc->sync_recv = false;
		target_proc->async_recv = false;
		target_proc->is_frozen = false;
		binder_inner_proc_unlock(target_proc);
		return 0;
@@ -4787,6 +4793,8 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info,
	 * for transactions to drain.
	 */
	binder_inner_proc_lock(target_proc);
	target_proc->sync_recv = false;
	target_proc->async_recv = false;
	target_proc->is_frozen = true;
	binder_inner_proc_unlock(target_proc);

@@ -4808,6 +4816,33 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info,
	return ret;
}

static int binder_ioctl_get_freezer_info(
				struct binder_frozen_status_info *info)
{
	struct binder_proc *target_proc;
	bool found = false;

	info->sync_recv = 0;
	info->async_recv = 0;

	mutex_lock(&binder_procs_lock);
	hlist_for_each_entry(target_proc, &binder_procs, proc_node) {
		if (target_proc->pid == info->pid) {
			found = true;
			binder_inner_proc_lock(target_proc);
			info->sync_recv |= target_proc->sync_recv;
			info->async_recv |= target_proc->async_recv;
			binder_inner_proc_unlock(target_proc);
		}
	}
	mutex_unlock(&binder_procs_lock);

	if (!found)
		return -EINVAL;

	return 0;
}

static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	int ret;
@@ -4986,6 +5021,24 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
			goto err;
		break;
	}
	case BINDER_GET_FROZEN_INFO: {
		struct binder_frozen_status_info info;

		if (copy_from_user(&info, ubuf, sizeof(info))) {
			ret = -EFAULT;
			goto err;
		}

		ret = binder_ioctl_get_freezer_info(&info);
		if (ret < 0)
			goto err;

		if (copy_to_user(ubuf, &info, sizeof(info))) {
			ret = -EFAULT;
			goto err;
		}
		break;
	}
	default:
		ret = -EINVAL;
		goto err;
@@ -5316,6 +5369,8 @@ static void binder_deferred_release(struct binder_proc *proc)

	proc->is_dead = true;
	proc->is_frozen = false;
	proc->sync_recv = false;
	proc->async_recv = false;
	threads = 0;
	active_transactions = 0;
	while ((n = rb_first(&proc->threads))) {
+6 −0
Original line number Diff line number Diff line
@@ -397,6 +397,10 @@ struct binder_priority {
 * @is_frozen:            process is frozen and unable to service
 *                        binder transactions
 *                        (protected by @inner_lock)
 * @sync_recv:            process received sync transactions since last frozen
 *                        (protected by @inner_lock)
 * @async_recv:           process received async transactions since last frozen
 *                        (protected by @inner_lock)
 * @freeze_wait:          waitqueue of processes waiting for all outstanding
 *                        transactions to be processed
 *                        (protected by @inner_lock)
@@ -443,6 +447,8 @@ struct binder_proc {
	int outstanding_txns;
	bool is_dead;
	bool is_frozen;
	bool sync_recv;
	bool async_recv;
	wait_queue_head_t freeze_wait;

	struct list_head todo;
+7 −0
Original line number Diff line number Diff line
@@ -271,6 +271,12 @@ struct binder_freeze_info {
	__u32            timeout_ms;
};

struct binder_frozen_status_info {
	__u32            pid;
	__u32            sync_recv;
	__u32            async_recv;
};

#define BINDER_WRITE_READ		_IOWR('b', 1, struct binder_write_read)
#define BINDER_SET_IDLE_TIMEOUT		_IOW('b', 3, __s64)
#define BINDER_SET_MAX_THREADS		_IOW('b', 5, __u32)
@@ -282,6 +288,7 @@ struct binder_freeze_info {
#define BINDER_GET_NODE_INFO_FOR_REF	_IOWR('b', 12, struct binder_node_info_for_ref)
#define BINDER_SET_CONTEXT_MGR_EXT	_IOW('b', 13, struct flat_binder_object)
#define BINDER_FREEZE			_IOW('b', 14, struct binder_freeze_info)
#define BINDER_GET_FROZEN_INFO		_IOWR('b', 15, struct binder_frozen_status_info)

/*
 * NOTE: Two special error codes you should check for when calling