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

Commit 8ac37e15 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "staging: android: binder: Move some of the logic into subfunction"

parents 8ac44e68 72acba3b
Loading
Loading
Loading
Loading
+220 −183
Original line number Diff line number Diff line
@@ -1718,89 +1718,12 @@ err_no_context_mgr_node:
		thread->return_error = return_error;
}

static int binder_thread_write(struct binder_proc *proc,
			struct binder_thread *thread,
			void __user *buffer, size_t size, size_t *consumed)
static void bc_increfs_done(struct binder_proc *proc,
		struct binder_thread *thread, uint32_t cmd,
		void __user *node_ptr, void __user *cookie)
{
	uint32_t cmd;
	void __user *ptr = buffer + *consumed;
	void __user *end = buffer + size;

	while (ptr < end && thread->return_error == BR_OK) {
		if (get_user(cmd, (uint32_t __user *)ptr))
			return -EFAULT;
		ptr += sizeof(uint32_t);
		trace_binder_command(cmd);
		if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.bc)) {
			binder_stats.bc[_IOC_NR(cmd)]++;
			proc->stats.bc[_IOC_NR(cmd)]++;
			thread->stats.bc[_IOC_NR(cmd)]++;
		}
		switch (cmd) {
		case BC_INCREFS:
		case BC_ACQUIRE:
		case BC_RELEASE:
		case BC_DECREFS: {
			uint32_t target;
			struct binder_ref *ref;
			const char *debug_string;

			if (get_user(target, (uint32_t __user *)ptr))
				return -EFAULT;
			ptr += sizeof(uint32_t);
			if (target == 0 && binder_context_mgr_node &&
			    (cmd == BC_INCREFS || cmd == BC_ACQUIRE)) {
				ref = binder_get_ref_for_node(proc,
					       binder_context_mgr_node);
				if (ref->desc != target) {
					binder_user_error("%d:%d tried to acquire reference to desc 0, got %d instead\n",
						proc->pid, thread->pid,
						ref->desc);
				}
			} else
				ref = binder_get_ref(proc, target);
			if (ref == NULL) {
				binder_user_error("%d:%d refcount change on invalid ref %d\n",
					proc->pid, thread->pid, target);
				break;
			}
			switch (cmd) {
			case BC_INCREFS:
				debug_string = "IncRefs";
				binder_inc_ref(ref, 0, NULL);
				break;
			case BC_ACQUIRE:
				debug_string = "Acquire";
				binder_inc_ref(ref, 1, NULL);
				break;
			case BC_RELEASE:
				debug_string = "Release";
				binder_dec_ref(ref, 1);
				break;
			case BC_DECREFS:
			default:
				debug_string = "DecRefs";
				binder_dec_ref(ref, 0);
				break;
			}
			binder_debug(BINDER_DEBUG_USER_REFS,
				     "%d:%d %s ref %d desc %d s %d w %d for node %d\n",
				     proc->pid, thread->pid, debug_string, ref->debug_id,
				     ref->desc, ref->strong, ref->weak, ref->node->debug_id);
			break;
		}
		case BC_INCREFS_DONE:
		case BC_ACQUIRE_DONE: {
			void __user *node_ptr;
			void __user *cookie;
	struct binder_node *node;

			if (get_user(node_ptr, (void * __user *)ptr))
				return -EFAULT;
			ptr += sizeof(void *);
			if (get_user(cookie, (void * __user *)ptr))
				return -EFAULT;
			ptr += sizeof(void *);
	node = binder_get_node(proc, node_ptr);
	if (node == NULL) {
		binder_user_error("%d:%d %s u%p no match\n",
@@ -1809,7 +1732,7 @@ static int binder_thread_write(struct binder_proc *proc,
			"BC_INCREFS_DONE" :
			"BC_ACQUIRE_DONE",
			node_ptr);
				break;
		return;
	}
	if (cookie != node->cookie) {
		binder_user_error("%d:%d %s u%p node %d cookie mismatch %p != %p\n",
@@ -1818,14 +1741,14 @@ static int binder_thread_write(struct binder_proc *proc,
			"BC_INCREFS_DONE" : "BC_ACQUIRE_DONE",
			node_ptr, node->debug_id,
			cookie, node->cookie);
				break;
		return;
	}
	if (cmd == BC_ACQUIRE_DONE) {
		if (node->pending_strong_ref == 0) {
			binder_user_error("%d:%d BC_ACQUIRE_DONE node %d has no pending acquire request\n",
				proc->pid, thread->pid,
				node->debug_id);
					break;
			return;
		}
		node->pending_strong_ref = 0;
	} else {
@@ -1833,7 +1756,7 @@ static int binder_thread_write(struct binder_proc *proc,
			binder_user_error("%d:%d BC_INCREFS_DONE node %d has no pending increfs request\n",
				proc->pid, thread->pid,
				node->debug_id);
					break;
			return;
		}
		node->pending_weak_ref = 0;
	}
@@ -1841,35 +1764,29 @@ static int binder_thread_write(struct binder_proc *proc,
	binder_debug(BINDER_DEBUG_USER_REFS,
		     "%d:%d %s node %d ls %d lw %d\n",
		     proc->pid, thread->pid,
				     cmd == BC_INCREFS_DONE ? "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE",
				     node->debug_id, node->local_strong_refs, node->local_weak_refs);
			break;
		     cmd == BC_INCREFS_DONE ?
		     "BC_INCREFS_DONE" :
		     "BC_ACQUIRE_DONE",
		     node->debug_id, node->local_strong_refs,
		     node->local_weak_refs);
	return;
}
		case BC_ATTEMPT_ACQUIRE:
			pr_err("BC_ATTEMPT_ACQUIRE not supported\n");
			return -EINVAL;
		case BC_ACQUIRE_RESULT:
			pr_err("BC_ACQUIRE_RESULT not supported\n");
			return -EINVAL;

		case BC_FREE_BUFFER: {
			void __user *data_ptr;
static void bc_free_buffer(struct binder_proc *proc,
		    struct binder_thread *thread, void __user *data_ptr)
{
	struct binder_buffer *buffer;

			if (get_user(data_ptr, (void * __user *)ptr))
				return -EFAULT;
			ptr += sizeof(void *);

	buffer = binder_buffer_lookup(proc, data_ptr);
	if (buffer == NULL) {
		binder_user_error("%d:%d BC_FREE_BUFFER u%p no match\n",
			proc->pid, thread->pid, data_ptr);
				break;
		return;
	}
	if (!buffer->allow_user_free) {
		binder_user_error("%d:%d BC_FREE_BUFFER u%p matched unreturned buffer\n",
			proc->pid, thread->pid, data_ptr);
				break;
		return;
	}
	binder_debug(BINDER_DEBUG_FREE_BUFFER,
		     "%d:%d BC_FREE_BUFFER u%p found buffer %d for %s transaction\n",
@@ -1890,69 +1807,16 @@ static int binder_thread_write(struct binder_proc *proc,
	trace_binder_transaction_buffer_release(buffer);
	binder_transaction_buffer_release(proc, buffer, NULL);
	binder_free_buf(proc, buffer);
			break;
		}

		case BC_TRANSACTION:
		case BC_REPLY: {
			struct binder_transaction_data tr;

			if (copy_from_user(&tr, ptr, sizeof(tr)))
				return -EFAULT;
			ptr += sizeof(tr);
			binder_transaction(proc, thread, &tr, cmd == BC_REPLY);
			break;
		}

		case BC_REGISTER_LOOPER:
			binder_debug(BINDER_DEBUG_THREADS,
				     "%d:%d BC_REGISTER_LOOPER\n",
				     proc->pid, thread->pid);
			if (thread->looper & BINDER_LOOPER_STATE_ENTERED) {
				thread->looper |= BINDER_LOOPER_STATE_INVALID;
				binder_user_error("%d:%d ERROR: BC_REGISTER_LOOPER called after BC_ENTER_LOOPER\n",
					proc->pid, thread->pid);
			} else if (proc->requested_threads == 0) {
				thread->looper |= BINDER_LOOPER_STATE_INVALID;
				binder_user_error("%d:%d ERROR: BC_REGISTER_LOOPER called without request\n",
					proc->pid, thread->pid);
			} else {
				proc->requested_threads--;
				proc->requested_threads_started++;
			}
			thread->looper |= BINDER_LOOPER_STATE_REGISTERED;
			break;
		case BC_ENTER_LOOPER:
			binder_debug(BINDER_DEBUG_THREADS,
				     "%d:%d BC_ENTER_LOOPER\n",
				     proc->pid, thread->pid);
			if (thread->looper & BINDER_LOOPER_STATE_REGISTERED) {
				thread->looper |= BINDER_LOOPER_STATE_INVALID;
				binder_user_error("%d:%d ERROR: BC_ENTER_LOOPER called after BC_REGISTER_LOOPER\n",
					proc->pid, thread->pid);
	return;
}
			thread->looper |= BINDER_LOOPER_STATE_ENTERED;
			break;
		case BC_EXIT_LOOPER:
			binder_debug(BINDER_DEBUG_THREADS,
				     "%d:%d BC_EXIT_LOOPER\n",
				     proc->pid, thread->pid);
			thread->looper |= BINDER_LOOPER_STATE_EXITED;
			break;

		case BC_REQUEST_DEATH_NOTIFICATION:
		case BC_CLEAR_DEATH_NOTIFICATION: {
			uint32_t target;
			void __user *cookie;
static void bc_clear_death_notif(struct binder_proc *proc,
		    struct binder_thread *thread, uint32_t cmd,
		    uint32_t target, void __user *cookie)
{
	struct binder_ref *ref;
	struct binder_ref_death *death;

			if (get_user(target, (uint32_t __user *)ptr))
				return -EFAULT;
			ptr += sizeof(uint32_t);
			if (get_user(cookie, (void __user * __user *)ptr))
				return -EFAULT;
			ptr += sizeof(void *);
	ref = binder_get_ref(proc, target);
	if (ref == NULL) {
		binder_user_error("%d:%d %s invalid ref %d\n",
@@ -1961,7 +1825,7 @@ static int binder_thread_write(struct binder_proc *proc,
			"BC_REQUEST_DEATH_NOTIFICATION" :
			"BC_CLEAR_DEATH_NOTIFICATION",
			target);
				break;
		return;
	}

	binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
@@ -1977,7 +1841,7 @@ static int binder_thread_write(struct binder_proc *proc,
		if (ref->death) {
			binder_user_error("%d:%d BC_REQUEST_DEATH_NOTIFICATION death notification already set\n",
				proc->pid, thread->pid);
					break;
			return;
		}
		death = kzalloc(sizeof(*death), GFP_KERNEL);
		if (death == NULL) {
@@ -1985,7 +1849,7 @@ static int binder_thread_write(struct binder_proc *proc,
			binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
				     "%d:%d BC_REQUEST_DEATH_NOTIFICATION failed\n",
				     proc->pid, thread->pid);
					break;
			return;
		}
		binder_stats_created(BINDER_STAT_DEATH);
		INIT_LIST_HEAD(&death->work.entry);
@@ -2004,14 +1868,14 @@ static int binder_thread_write(struct binder_proc *proc,
		if (ref->death == NULL) {
			binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification not active\n",
				proc->pid, thread->pid);
					break;
			return;
		}
		death = ref->death;
		if (death->cookie != cookie) {
			binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch %p != %p\n",
				proc->pid, thread->pid,
				death->cookie, cookie);
					break;
			return;
		}
		ref->death = NULL;
		if (list_empty(&death->work.entry)) {
@@ -2027,20 +1891,20 @@ static int binder_thread_write(struct binder_proc *proc,
			death->work.type = BINDER_WORK_DEAD_BINDER_AND_CLEAR;
		}
	}
		} break;
		case BC_DEAD_BINDER_DONE: {
	return;
}

static void bc_dead_binder_done(struct binder_proc *proc,
		    struct binder_thread *thread, void __user *cookie)
{
	struct binder_work *w;
			void __user *cookie;
	struct binder_ref_death *death = NULL;
			if (get_user(cookie, (void __user * __user *)ptr))
				return -EFAULT;

			ptr += sizeof(void *);
	list_for_each_entry(w, &proc->delivered_death, entry) {
		struct binder_ref_death *tmp_death = container_of(w, struct binder_ref_death, work);
		if (tmp_death->cookie == cookie) {
			death = tmp_death;
					break;
			return;
		}
	}
	binder_debug(BINDER_DEBUG_DEAD_BINDER,
@@ -2049,7 +1913,7 @@ static int binder_thread_write(struct binder_proc *proc,
	if (death == NULL) {
		binder_user_error("%d:%d BC_DEAD_BINDER_DONE %p not found\n",
			proc->pid, thread->pid, cookie);
				break;
		return;
	}

	list_del_init(&death->work.entry);
@@ -2062,8 +1926,181 @@ static int binder_thread_write(struct binder_proc *proc,
			wake_up_interruptible(&proc->wait);
		}
	}
		} break;
	return;
}

static int binder_thread_write(struct binder_proc *proc,
			struct binder_thread *thread,
			void __user *buffer, size_t size, size_t *consumed)
{
	uint32_t cmd;
	void __user *ptr = buffer + *consumed;
	void __user *end = buffer + size;

	while (ptr < end && thread->return_error == BR_OK) {
		if (get_user(cmd, (uint32_t __user *)ptr))
			return -EFAULT;
		ptr += sizeof(uint32_t);
		trace_binder_command(cmd);
		if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.bc)) {
			binder_stats.bc[_IOC_NR(cmd)]++;
			proc->stats.bc[_IOC_NR(cmd)]++;
			thread->stats.bc[_IOC_NR(cmd)]++;
		}
		switch (cmd) {
		case BC_INCREFS:
		case BC_ACQUIRE:
		case BC_RELEASE:
		case BC_DECREFS: {
			uint32_t target;
			struct binder_ref *ref;
			const char *debug_string;

			if (get_user(target, (uint32_t __user *)ptr))
				return -EFAULT;
			ptr += sizeof(uint32_t);
			if (target == 0 && binder_context_mgr_node &&
			    (cmd == BC_INCREFS || cmd == BC_ACQUIRE)) {
				ref = binder_get_ref_for_node(proc,
					       binder_context_mgr_node);
				if (ref->desc != target) {
					binder_user_error("%d:%d tried to acquire reference to desc 0, got %d instead\n",
						proc->pid, thread->pid,
						ref->desc);
				}
			} else
				ref = binder_get_ref(proc, target);
			if (ref == NULL) {
				binder_user_error("%d:%d refcount change on invalid ref %d\n",
					proc->pid, thread->pid, target);
				break;
			}
			switch (cmd) {
			case BC_INCREFS:
				debug_string = "IncRefs";
				binder_inc_ref(ref, 0, NULL);
				break;
			case BC_ACQUIRE:
				debug_string = "Acquire";
				binder_inc_ref(ref, 1, NULL);
				break;
			case BC_RELEASE:
				debug_string = "Release";
				binder_dec_ref(ref, 1);
				break;
			case BC_DECREFS:
			default:
				debug_string = "DecRefs";
				binder_dec_ref(ref, 0);
				break;
			}
			binder_debug(BINDER_DEBUG_USER_REFS,
				     "%d:%d %s ref %d desc %d s %d w %d for node %d\n",
				     proc->pid, thread->pid, debug_string, ref->debug_id,
				     ref->desc, ref->strong, ref->weak, ref->node->debug_id);
			break;
		}
		case BC_INCREFS_DONE:
		case BC_ACQUIRE_DONE: {
			void __user *node_ptr;
			void __user *cookie;

			if (get_user(node_ptr, (void * __user *)ptr))
				return -EFAULT;
			ptr += sizeof(void *);
			if (get_user(cookie, (void * __user *)ptr))
				return -EFAULT;
			ptr += sizeof(void *);
			bc_increfs_done(proc, thread, cmd, node_ptr, cookie);
			break;
		}
		case BC_ATTEMPT_ACQUIRE:
			pr_err("BC_ATTEMPT_ACQUIRE not supported\n");
			return -EINVAL;
		case BC_ACQUIRE_RESULT:
			pr_err("BC_ACQUIRE_RESULT not supported\n");
			return -EINVAL;

		case BC_FREE_BUFFER: {
			void __user *data_ptr;

			if (get_user(data_ptr, (void * __user *)ptr))
				return -EFAULT;
			ptr += sizeof(void *);
			bc_free_buffer(proc, thread, data_ptr);
			break;
		}

		case BC_TRANSACTION:
		case BC_REPLY: {
			struct binder_transaction_data tr;

			if (copy_from_user(&tr, ptr, sizeof(tr)))
				return -EFAULT;
			ptr += sizeof(tr);
			binder_transaction(proc, thread, &tr, cmd == BC_REPLY);
			break;
		}

		case BC_REGISTER_LOOPER:
			binder_debug(BINDER_DEBUG_THREADS,
				     "%d:%d BC_REGISTER_LOOPER\n",
				     proc->pid, thread->pid);
			if (thread->looper & BINDER_LOOPER_STATE_ENTERED) {
				thread->looper |= BINDER_LOOPER_STATE_INVALID;
				binder_user_error("%d:%d ERROR: BC_REGISTER_LOOPER called after BC_ENTER_LOOPER\n",
					proc->pid, thread->pid);
			} else if (proc->requested_threads == 0) {
				thread->looper |= BINDER_LOOPER_STATE_INVALID;
				binder_user_error("%d:%d ERROR: BC_REGISTER_LOOPER called without request\n",
					proc->pid, thread->pid);
			} else {
				proc->requested_threads--;
				proc->requested_threads_started++;
			}
			thread->looper |= BINDER_LOOPER_STATE_REGISTERED;
			break;
		case BC_ENTER_LOOPER:
			binder_debug(BINDER_DEBUG_THREADS,
				     "%d:%d BC_ENTER_LOOPER\n",
				     proc->pid, thread->pid);
			if (thread->looper & BINDER_LOOPER_STATE_REGISTERED) {
				thread->looper |= BINDER_LOOPER_STATE_INVALID;
				binder_user_error("%d:%d ERROR: BC_ENTER_LOOPER called after BC_REGISTER_LOOPER\n",
					proc->pid, thread->pid);
			}
			thread->looper |= BINDER_LOOPER_STATE_ENTERED;
			break;
		case BC_EXIT_LOOPER:
			binder_debug(BINDER_DEBUG_THREADS,
				     "%d:%d BC_EXIT_LOOPER\n",
				     proc->pid, thread->pid);
			thread->looper |= BINDER_LOOPER_STATE_EXITED;
			break;

		case BC_REQUEST_DEATH_NOTIFICATION:
		case BC_CLEAR_DEATH_NOTIFICATION: {
			uint32_t target;
			void __user *cookie;

			if (get_user(target, (uint32_t __user *)ptr))
				return -EFAULT;
			ptr += sizeof(uint32_t);
			if (get_user(cookie, (void __user * __user *)ptr))
				return -EFAULT;
			ptr += sizeof(void *);
			bc_clear_death_notif(proc, thread, cmd, target, cookie);
			break;
		}
		case BC_DEAD_BINDER_DONE: {
			void __user *cookie;

			if (get_user(cookie, (void __user * __user *)ptr))
				return -EFAULT;
			ptr += sizeof(void *);
			bc_dead_binder_done(proc, thread, cookie);
			break;
		}
		default:
			pr_err("%d:%d unknown command %d\n",
			       proc->pid, thread->pid, cmd);