lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1432854511-33320-4-git-send-email-riandrews@android.com>
Date:	Thu, 28 May 2015 16:08:21 -0700
From:	Riley Andrews <riandrews@...roid.com>
To:	linux-kernel@...r.kernel.org,
	Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
	Arve Hjønnevåg <arve@...roid.com>,
	Riley Andrews <riandrews@...roid.com>,
	devel@...verdev.osuosl.org
Subject: [PATCH 03/13] android: binder: refactor binder_thread_write

Give every case in the switch statement its own dedicated function.
Remove the process argument to binder_transact, as it can be derived
from the thread argument as with all of the other newly created
functions.

Signed-off-by: Riley Andrews <riandrews@...roid.com>
---
 drivers/android/binder.c | 613 +++++++++++++++++++++++++++--------------------
 1 file changed, 350 insertions(+), 263 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 2069759..e47c2d4 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -1314,8 +1314,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
 	}
 }
 
-static void binder_transaction(struct binder_proc *proc,
-			       struct binder_thread *thread,
+static void binder_transaction(struct binder_thread *thread,
 			       struct binder_transaction_data *tr, int reply)
 {
 	struct binder_transaction *t;
@@ -1328,6 +1327,7 @@ static void binder_transaction(struct binder_proc *proc,
 	wait_queue_head_t *target_wait;
 	struct binder_transaction *in_reply_to = NULL;
 	struct binder_transaction_log_entry *e;
+	struct binder_proc *proc = thread->proc;
 	uint32_t return_error;
 
 	e = binder_transaction_log_add(&binder_transaction_log);
@@ -1752,10 +1752,329 @@ err_no_context_mgr_node:
 		thread->return_error = return_error;
 }
 
+static void binder_call_inc_dec_ref(struct binder_thread *thread,
+				    uint32_t target, uint32_t cmd)
+{
+	struct binder_proc *proc = thread->proc;
+	struct binder_ref *ref;
+	const char *debug_string;
+
+	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);
+			return;
+		}
+	} else {
+		ref = binder_get_ref(proc, target);
+	}
+	if (!ref) {
+		binder_user_error("%d:%d refcount change on invalid ref %d\n",
+				  proc->pid, thread->pid, target);
+		return;
+	}
+	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);
+}
+
+static void binder_call_inc_ref_done(struct binder_thread *thread,
+				     binder_uintptr_t node_ptr,
+				     binder_uintptr_t cookie, uint32_t cmd)
+{
+	struct binder_node *node;
+	struct binder_proc *proc = thread->proc;
+
+	node = binder_get_node(proc, node_ptr);
+	if (!node) {
+		binder_user_error("%d:%d %s u%016llx no match\n",
+				  proc->pid, thread->pid,
+				  cmd == BC_INCREFS_DONE ?
+				  "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE",
+				  (u64)node_ptr);
+		return;
+	}
+	if (cookie != node->cookie) {
+		binder_user_error("%d:%d %s u%016llx node %d cookie mismatch %016llx != %016llx\n",
+				  proc->pid, thread->pid,
+				  cmd == BC_INCREFS_DONE ?
+				  "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE",
+				  (u64)node_ptr, node->debug_id,
+				  (u64)cookie, (u64)node->cookie);
+		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);
+			return;
+		}
+		node->pending_strong_ref = 0;
+	} else {
+		if (node->pending_weak_ref == 0) {
+			binder_user_error("%d:%d BC_INCREFS_DONE node %d has no pending increfs request\n",
+					  proc->pid, thread->pid,
+					  node->debug_id);
+			return;
+		}
+		node->pending_weak_ref = 0;
+	}
+	binder_dec_node(node, cmd == BC_ACQUIRE_DONE, 0);
+	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);
+}
+
+static void binder_call_free_buffer(struct binder_thread *thread,
+				    binder_uintptr_t data_ptr)
+{
+	struct binder_buffer *buffer;
+	struct binder_proc *proc = thread->proc;
+
+	buffer = binder_buffer_lookup(proc, data_ptr);
+	if (!buffer) {
+		binder_user_error("%d:%d BC_FREE_BUFFER u%016llx no match\n",
+				  proc->pid, thread->pid, (u64)data_ptr);
+		return;
+	}
+	if (!buffer->allow_user_free) {
+		binder_user_error("%d:%d BC_FREE_BUFFER u%016llx matched unreturned buffer\n",
+				  proc->pid, thread->pid, (u64)data_ptr);
+		return;
+	}
+	binder_debug(BINDER_DEBUG_FREE_BUFFER,
+		     "%d:%d BC_FREE_BUFFER u%016llx found buffer %d for %s transaction\n",
+		     proc->pid, thread->pid, (u64)data_ptr, buffer->debug_id,
+		     buffer->transaction ? "active" : "finished");
+
+	if (buffer->transaction) {
+		buffer->transaction->buffer = NULL;
+		buffer->transaction = NULL;
+	}
+	if (buffer->async_transaction && buffer->target_node) {
+		BUG_ON(!buffer->target_node->has_async_transaction);
+		if (list_empty(&buffer->target_node->async_todo))
+			buffer->target_node->has_async_transaction = 0;
+		else
+			list_move_tail(buffer->target_node->async_todo.next,
+				       &thread->todo);
+	}
+	trace_binder_transaction_buffer_release(buffer);
+	binder_transaction_buffer_release(proc, buffer, NULL);
+	binder_free_buf(proc, buffer);
+}
+
+static void binder_call_register_looper(struct binder_thread *thread)
+{
+	struct binder_proc *proc = thread->proc;
+
+	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;
+}
+
+static void binder_call_enter_looper(struct binder_thread *thread)
+{
+	struct binder_proc *proc = thread->proc;
+
+	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;
+}
+
+static void binder_call_req_death_notification(struct binder_thread *thread,
+					       uint32_t target,
+					       binder_uintptr_t cookie)
+{
+	struct binder_ref *ref;
+	struct binder_ref_death *death;
+	struct binder_proc *proc = thread->proc;
+
+	ref = binder_get_ref(proc, target);
+	if (!ref) {
+		binder_user_error("%d:%d %s invalid ref %d\n",
+				  proc->pid, thread->pid,
+				  "BC_REQUEST_DEATH_NOTIFICATION",
+				  target);
+		return;
+	}
+
+	binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
+		     "%d:%d %s %016llx ref %d desc %d s %d w %d for node %d\n",
+		     proc->pid, thread->pid,
+		     "BC_REQUEST_DEATH_NOTIFICATION",
+		     (u64)cookie, ref->debug_id, ref->desc,
+		     ref->strong, ref->weak, ref->node->debug_id);
+
+	if (ref->death) {
+		binder_user_error("%d:%d BC_REQUEST_DEATH_NOTIFICATION death notification already set\n",
+				  proc->pid, thread->pid);
+		return;
+	}
+	death = kzalloc(sizeof(*death), GFP_KERNEL);
+	if (!death) {
+		thread->return_error = BR_ERROR;
+		binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
+			     "%d:%d BC_REQUEST_DEATH_NOTIFICATION failed\n",
+			     proc->pid, thread->pid);
+		return;
+	}
+	binder_stats_created(BINDER_STAT_DEATH);
+	INIT_LIST_HEAD(&death->work.entry);
+	death->cookie = cookie;
+	ref->death = death;
+	if (!ref->node->proc) {
+		ref->death->work.type = BINDER_WORK_DEAD_BINDER;
+		if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
+				      BINDER_LOOPER_STATE_ENTERED)) {
+			list_add_tail(&ref->death->work.entry,
+				      &thread->todo);
+		} else {
+			list_add_tail(&ref->death->work.entry,
+				      &proc->todo);
+			wake_up_interruptible(&proc->wait);
+		}
+	}
+}
+
+static void binder_call_clear_death_notification(struct binder_thread *thread,
+						 uint32_t target,
+						 binder_uintptr_t cookie)
+{
+	struct binder_ref *ref;
+	struct binder_ref_death *death;
+	struct binder_proc *proc = thread->proc;
+
+	ref = binder_get_ref(proc, target);
+	if (!ref) {
+		binder_user_error("%d:%d %s invalid ref %d\n",
+				  proc->pid, thread->pid,
+				  "BC_CLEAR_DEATH_NOTIFICATION",
+				  target);
+		return;
+	}
+
+	binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
+		     "%d:%d %s %016llx ref %d desc %d s %d w %d for node %d\n",
+		     proc->pid, thread->pid,
+		     "BC_CLEAR_DEATH_NOTIFICATION",
+		     (u64)cookie, ref->debug_id, ref->desc,
+		     ref->strong, ref->weak, ref->node->debug_id);
+
+	if (!ref->death) {
+		binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification not active\n",
+				  proc->pid, thread->pid);
+		return;
+	}
+	death = ref->death;
+	if (death->cookie != cookie) {
+		binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch %016llx != %016llx\n",
+				  proc->pid, thread->pid,
+				  (u64)death->cookie, (u64)cookie);
+		return;
+	}
+	ref->death = NULL;
+	if (list_empty(&death->work.entry)) {
+		death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION;
+		if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
+				      BINDER_LOOPER_STATE_ENTERED)) {
+			list_add_tail(&death->work.entry,
+				      &thread->todo);
+		} else {
+			list_add_tail(&death->work.entry, &proc->todo);
+			wake_up_interruptible(&proc->wait);
+		}
+	} else {
+		BUG_ON(death->work.type != BINDER_WORK_DEAD_BINDER);
+		death->work.type = BINDER_WORK_DEAD_BINDER_AND_CLEAR;
+	}
+}
+
+static void binder_call_dead_binder_done(struct binder_thread *thread,
+					 binder_uintptr_t cookie)
+{
+	struct binder_work *work;
+	struct binder_ref_death *death = NULL;
+	struct binder_proc *proc = thread->proc;
+
+	list_for_each_entry(work, &proc->delivered_death, entry) {
+		struct binder_ref_death *tmp_death;
+
+		tmp_death = container_of(work, struct binder_ref_death, work);
+		if (tmp_death->cookie == cookie) {
+			death = tmp_death;
+			break;
+		}
+	}
+	binder_debug(BINDER_DEBUG_DEAD_BINDER,
+		     "%d:%d BC_DEAD_BINDER_DONE %016llx found %p\n",
+		     proc->pid, thread->pid, (u64)cookie,
+		     death);
+	if (!death) {
+		binder_user_error("%d:%d BC_DEAD_BINDER_DONE %016llx not found\n",
+				  proc->pid, thread->pid, (u64)cookie);
+		return;
+	}
+
+	list_del_init(&death->work.entry);
+	if (death->work.type == BINDER_WORK_DEAD_BINDER_AND_CLEAR) {
+		death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION;
+		if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
+				      BINDER_LOOPER_STATE_ENTERED)) {
+			list_add_tail(&death->work.entry, &thread->todo);
+		} else {
+			list_add_tail(&death->work.entry, &proc->todo);
+			wake_up_interruptible(&proc->wait);
+		}
+	}
+}
+
 static int binder_thread_write(struct binder_proc *proc,
-			struct binder_thread *thread,
-			binder_uintptr_t binder_buffer, size_t size,
-			binder_size_t *consumed)
+			       struct binder_thread *thread,
+			       binder_uintptr_t binder_buffer, size_t size,
+			       binder_size_t *consumed)
 {
 	uint32_t cmd;
 	void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
@@ -1778,58 +2097,17 @@ static int binder_thread_write(struct binder_proc *proc,
 		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);
+			binder_call_inc_dec_ref(thread, target, cmd);
 			break;
 		}
 		case BC_INCREFS_DONE:
 		case BC_ACQUIRE_DONE: {
 			binder_uintptr_t node_ptr;
 			binder_uintptr_t cookie;
-			struct binder_node *node;
 
 			if (get_user(node_ptr, (binder_uintptr_t __user *)ptr))
 				return -EFAULT;
@@ -1837,48 +2115,7 @@ static int binder_thread_write(struct binder_proc *proc,
 			if (get_user(cookie, (binder_uintptr_t __user *)ptr))
 				return -EFAULT;
 			ptr += sizeof(binder_uintptr_t);
-			node = binder_get_node(proc, node_ptr);
-			if (node == NULL) {
-				binder_user_error("%d:%d %s u%016llx no match\n",
-					proc->pid, thread->pid,
-					cmd == BC_INCREFS_DONE ?
-					"BC_INCREFS_DONE" :
-					"BC_ACQUIRE_DONE",
-					(u64)node_ptr);
-				break;
-			}
-			if (cookie != node->cookie) {
-				binder_user_error("%d:%d %s u%016llx node %d cookie mismatch %016llx != %016llx\n",
-					proc->pid, thread->pid,
-					cmd == BC_INCREFS_DONE ?
-					"BC_INCREFS_DONE" : "BC_ACQUIRE_DONE",
-					(u64)node_ptr, node->debug_id,
-					(u64)cookie, (u64)node->cookie);
-				break;
-			}
-			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;
-				}
-				node->pending_strong_ref = 0;
-			} else {
-				if (node->pending_weak_ref == 0) {
-					binder_user_error("%d:%d BC_INCREFS_DONE node %d has no pending increfs request\n",
-						proc->pid, thread->pid,
-						node->debug_id);
-					break;
-				}
-				node->pending_weak_ref = 0;
-			}
-			binder_dec_node(node, cmd == BC_ACQUIRE_DONE, 0);
-			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);
+			binder_call_inc_ref_done(thread, node_ptr, cookie, cmd);
 			break;
 		}
 		case BC_ATTEMPT_ACQUIRE:
@@ -1887,49 +2124,15 @@ static int binder_thread_write(struct binder_proc *proc,
 		case BC_ACQUIRE_RESULT:
 			pr_err("BC_ACQUIRE_RESULT not supported\n");
 			return -EINVAL;
-
 		case BC_FREE_BUFFER: {
 			binder_uintptr_t data_ptr;
-			struct binder_buffer *buffer;
 
 			if (get_user(data_ptr, (binder_uintptr_t __user *)ptr))
 				return -EFAULT;
 			ptr += sizeof(binder_uintptr_t);
-
-			buffer = binder_buffer_lookup(proc, data_ptr);
-			if (buffer == NULL) {
-				binder_user_error("%d:%d BC_FREE_BUFFER u%016llx no match\n",
-					proc->pid, thread->pid, (u64)data_ptr);
-				break;
-			}
-			if (!buffer->allow_user_free) {
-				binder_user_error("%d:%d BC_FREE_BUFFER u%016llx matched unreturned buffer\n",
-					proc->pid, thread->pid, (u64)data_ptr);
-				break;
-			}
-			binder_debug(BINDER_DEBUG_FREE_BUFFER,
-				     "%d:%d BC_FREE_BUFFER u%016llx found buffer %d for %s transaction\n",
-				     proc->pid, thread->pid, (u64)data_ptr,
-				     buffer->debug_id,
-				     buffer->transaction ? "active" : "finished");
-
-			if (buffer->transaction) {
-				buffer->transaction->buffer = NULL;
-				buffer->transaction = NULL;
-			}
-			if (buffer->async_transaction && buffer->target_node) {
-				BUG_ON(!buffer->target_node->has_async_transaction);
-				if (list_empty(&buffer->target_node->async_todo))
-					buffer->target_node->has_async_transaction = 0;
-				else
-					list_move_tail(buffer->target_node->async_todo.next, &thread->todo);
-			}
-			trace_binder_transaction_buffer_release(buffer);
-			binder_transaction_buffer_release(proc, buffer, NULL);
-			binder_free_buf(proc, buffer);
+			binder_call_free_buffer(thread, data_ptr);
 			break;
 		}
-
 		case BC_TRANSACTION:
 		case BC_REPLY: {
 			struct binder_transaction_data tr;
@@ -1937,38 +2140,14 @@ static int binder_thread_write(struct binder_proc *proc,
 			if (copy_from_user(&tr, ptr, sizeof(tr)))
 				return -EFAULT;
 			ptr += sizeof(tr);
-			binder_transaction(proc, thread, &tr, cmd == BC_REPLY);
+			binder_transaction(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;
+			binder_call_register_looper(thread);
 			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;
+			binder_call_enter_looper(thread);
 			break;
 		case BC_EXIT_LOOPER:
 			binder_debug(BINDER_DEBUG_THREADS,
@@ -1976,13 +2155,23 @@ static int binder_thread_write(struct binder_proc *proc,
 				     proc->pid, thread->pid);
 			thread->looper |= BINDER_LOOPER_STATE_EXITED;
 			break;
+		case BC_REQUEST_DEATH_NOTIFICATION: {
+			uint32_t target;
+			binder_uintptr_t cookie;
 
-		case BC_REQUEST_DEATH_NOTIFICATION:
+			if (get_user(target, (uint32_t __user *)ptr))
+				return -EFAULT;
+			ptr += sizeof(uint32_t);
+			if (get_user(cookie, (binder_uintptr_t __user *)ptr))
+				return -EFAULT;
+			ptr += sizeof(binder_uintptr_t);
+			binder_call_req_death_notification(thread, target,
+							   cookie);
+			break;
+		}
 		case BC_CLEAR_DEATH_NOTIFICATION: {
 			uint32_t target;
 			binder_uintptr_t cookie;
-			struct binder_ref *ref;
-			struct binder_ref_death *death;
 
 			if (get_user(target, (uint32_t __user *)ptr))
 				return -EFAULT;
@@ -1990,121 +2179,19 @@ static int binder_thread_write(struct binder_proc *proc,
 			if (get_user(cookie, (binder_uintptr_t __user *)ptr))
 				return -EFAULT;
 			ptr += sizeof(binder_uintptr_t);
-			ref = binder_get_ref(proc, target);
-			if (ref == NULL) {
-				binder_user_error("%d:%d %s invalid ref %d\n",
-					proc->pid, thread->pid,
-					cmd == BC_REQUEST_DEATH_NOTIFICATION ?
-					"BC_REQUEST_DEATH_NOTIFICATION" :
-					"BC_CLEAR_DEATH_NOTIFICATION",
-					target);
-				break;
-			}
-
-			binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
-				     "%d:%d %s %016llx ref %d desc %d s %d w %d for node %d\n",
-				     proc->pid, thread->pid,
-				     cmd == BC_REQUEST_DEATH_NOTIFICATION ?
-				     "BC_REQUEST_DEATH_NOTIFICATION" :
-				     "BC_CLEAR_DEATH_NOTIFICATION",
-				     (u64)cookie, ref->debug_id, ref->desc,
-				     ref->strong, ref->weak, ref->node->debug_id);
-
-			if (cmd == BC_REQUEST_DEATH_NOTIFICATION) {
-				if (ref->death) {
-					binder_user_error("%d:%d BC_REQUEST_DEATH_NOTIFICATION death notification already set\n",
-						proc->pid, thread->pid);
-					break;
-				}
-				death = kzalloc(sizeof(*death), GFP_KERNEL);
-				if (death == NULL) {
-					thread->return_error = BR_ERROR;
-					binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
-						     "%d:%d BC_REQUEST_DEATH_NOTIFICATION failed\n",
-						     proc->pid, thread->pid);
-					break;
-				}
-				binder_stats_created(BINDER_STAT_DEATH);
-				INIT_LIST_HEAD(&death->work.entry);
-				death->cookie = cookie;
-				ref->death = death;
-				if (ref->node->proc == NULL) {
-					ref->death->work.type = BINDER_WORK_DEAD_BINDER;
-					if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {
-						list_add_tail(&ref->death->work.entry, &thread->todo);
-					} else {
-						list_add_tail(&ref->death->work.entry, &proc->todo);
-						wake_up_interruptible(&proc->wait);
-					}
-				}
-			} else {
-				if (ref->death == NULL) {
-					binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification not active\n",
-						proc->pid, thread->pid);
-					break;
-				}
-				death = ref->death;
-				if (death->cookie != cookie) {
-					binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch %016llx != %016llx\n",
-						proc->pid, thread->pid,
-						(u64)death->cookie,
-						(u64)cookie);
-					break;
-				}
-				ref->death = NULL;
-				if (list_empty(&death->work.entry)) {
-					death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION;
-					if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {
-						list_add_tail(&death->work.entry, &thread->todo);
-					} else {
-						list_add_tail(&death->work.entry, &proc->todo);
-						wake_up_interruptible(&proc->wait);
-					}
-				} else {
-					BUG_ON(death->work.type != BINDER_WORK_DEAD_BINDER);
-					death->work.type = BINDER_WORK_DEAD_BINDER_AND_CLEAR;
-				}
-			}
-		} break;
+			binder_call_clear_death_notification(thread, target,
+							     cookie);
+			break;
+		}
 		case BC_DEAD_BINDER_DONE: {
-			struct binder_work *w;
 			binder_uintptr_t cookie;
-			struct binder_ref_death *death = NULL;
 
 			if (get_user(cookie, (binder_uintptr_t __user *)ptr))
 				return -EFAULT;
-
 			ptr += sizeof(cookie);
-			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;
-				}
-			}
-			binder_debug(BINDER_DEBUG_DEAD_BINDER,
-				     "%d:%d BC_DEAD_BINDER_DONE %016llx found %p\n",
-				     proc->pid, thread->pid, (u64)cookie,
-				     death);
-			if (death == NULL) {
-				binder_user_error("%d:%d BC_DEAD_BINDER_DONE %016llx not found\n",
-					proc->pid, thread->pid, (u64)cookie);
-				break;
-			}
-
-			list_del_init(&death->work.entry);
-			if (death->work.type == BINDER_WORK_DEAD_BINDER_AND_CLEAR) {
-				death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION;
-				if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {
-					list_add_tail(&death->work.entry, &thread->todo);
-				} else {
-					list_add_tail(&death->work.entry, &proc->todo);
-					wake_up_interruptible(&proc->wait);
-				}
-			}
-		} break;
-
+			binder_call_dead_binder_done(thread, cookie);
+			break;
+		}
 		default:
 			pr_err("%d:%d unknown command %d\n",
 			       proc->pid, thread->pid, cmd);
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ