mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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. Signed-off-by: Marco Ballesio <balejs@google.com> Signed-off-by: Li Li <dualli@google.com> Acked-by: Todd Kjos <tkjos@google.com> Link: https://lore.kernel.org/r/20210316011630.1121213-4-dualli@chromium.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
		
							parent
							
								
									95c16f9d9c
								
							
						
					
					
						commit
						ae28c1be1e
					
				
					 3 changed files with 68 additions and 0 deletions
				
			
		| 
						 | 
					@ -2360,6 +2360,10 @@ static int binder_proc_transaction(struct binder_transaction *t,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	binder_inner_proc_lock(proc);
 | 
						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 ||
 | 
						if ((proc->is_frozen && !oneway) || proc->is_dead ||
 | 
				
			||||||
			(thread && thread->is_dead)) {
 | 
								(thread && thread->is_dead)) {
 | 
				
			||||||
| 
						 | 
					@ -4634,6 +4638,8 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!info->enable) {
 | 
						if (!info->enable) {
 | 
				
			||||||
		binder_inner_proc_lock(target_proc);
 | 
							binder_inner_proc_lock(target_proc);
 | 
				
			||||||
 | 
							target_proc->sync_recv = false;
 | 
				
			||||||
 | 
							target_proc->async_recv = false;
 | 
				
			||||||
		target_proc->is_frozen = false;
 | 
							target_proc->is_frozen = false;
 | 
				
			||||||
		binder_inner_proc_unlock(target_proc);
 | 
							binder_inner_proc_unlock(target_proc);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
| 
						 | 
					@ -4645,6 +4651,8 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info,
 | 
				
			||||||
	 * for transactions to drain.
 | 
						 * for transactions to drain.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	binder_inner_proc_lock(target_proc);
 | 
						binder_inner_proc_lock(target_proc);
 | 
				
			||||||
 | 
						target_proc->sync_recv = false;
 | 
				
			||||||
 | 
						target_proc->async_recv = false;
 | 
				
			||||||
	target_proc->is_frozen = true;
 | 
						target_proc->is_frozen = true;
 | 
				
			||||||
	binder_inner_proc_unlock(target_proc);
 | 
						binder_inner_proc_unlock(target_proc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4666,6 +4674,33 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info,
 | 
				
			||||||
	return ret;
 | 
						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)
 | 
					static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
| 
						 | 
					@ -4844,6 +4879,24 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 | 
				
			||||||
			goto err;
 | 
								goto err;
 | 
				
			||||||
		break;
 | 
							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:
 | 
						default:
 | 
				
			||||||
		ret = -EINVAL;
 | 
							ret = -EINVAL;
 | 
				
			||||||
		goto err;
 | 
							goto err;
 | 
				
			||||||
| 
						 | 
					@ -5154,6 +5207,8 @@ static void binder_deferred_release(struct binder_proc *proc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	proc->is_dead = true;
 | 
						proc->is_dead = true;
 | 
				
			||||||
	proc->is_frozen = false;
 | 
						proc->is_frozen = false;
 | 
				
			||||||
 | 
						proc->sync_recv = false;
 | 
				
			||||||
 | 
						proc->async_recv = false;
 | 
				
			||||||
	threads = 0;
 | 
						threads = 0;
 | 
				
			||||||
	active_transactions = 0;
 | 
						active_transactions = 0;
 | 
				
			||||||
	while ((n = rb_first(&proc->threads))) {
 | 
						while ((n = rb_first(&proc->threads))) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -376,6 +376,10 @@ struct binder_ref {
 | 
				
			||||||
 * @is_frozen:            process is frozen and unable to service
 | 
					 * @is_frozen:            process is frozen and unable to service
 | 
				
			||||||
 *                        binder transactions
 | 
					 *                        binder transactions
 | 
				
			||||||
 *                        (protected by @inner_lock)
 | 
					 *                        (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
 | 
					 * @freeze_wait:          waitqueue of processes waiting for all outstanding
 | 
				
			||||||
 *                        transactions to be processed
 | 
					 *                        transactions to be processed
 | 
				
			||||||
 *                        (protected by @inner_lock)
 | 
					 *                        (protected by @inner_lock)
 | 
				
			||||||
| 
						 | 
					@ -422,6 +426,8 @@ struct binder_proc {
 | 
				
			||||||
	int outstanding_txns;
 | 
						int outstanding_txns;
 | 
				
			||||||
	bool is_dead;
 | 
						bool is_dead;
 | 
				
			||||||
	bool is_frozen;
 | 
						bool is_frozen;
 | 
				
			||||||
 | 
						bool sync_recv;
 | 
				
			||||||
 | 
						bool async_recv;
 | 
				
			||||||
	wait_queue_head_t freeze_wait;
 | 
						wait_queue_head_t freeze_wait;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct list_head todo;
 | 
						struct list_head todo;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -223,6 +223,12 @@ struct binder_freeze_info {
 | 
				
			||||||
	__u32            timeout_ms;
 | 
						__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_WRITE_READ		_IOWR('b', 1, struct binder_write_read)
 | 
				
			||||||
#define BINDER_SET_IDLE_TIMEOUT		_IOW('b', 3, __s64)
 | 
					#define BINDER_SET_IDLE_TIMEOUT		_IOW('b', 3, __s64)
 | 
				
			||||||
#define BINDER_SET_MAX_THREADS		_IOW('b', 5, __u32)
 | 
					#define BINDER_SET_MAX_THREADS		_IOW('b', 5, __u32)
 | 
				
			||||||
| 
						 | 
					@ -234,6 +240,7 @@ struct binder_freeze_info {
 | 
				
			||||||
#define BINDER_GET_NODE_INFO_FOR_REF	_IOWR('b', 12, struct binder_node_info_for_ref)
 | 
					#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_SET_CONTEXT_MGR_EXT	_IOW('b', 13, struct flat_binder_object)
 | 
				
			||||||
#define BINDER_FREEZE			_IOW('b', 14, struct binder_freeze_info)
 | 
					#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
 | 
					 * NOTE: Two special error codes you should check for when calling
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue