diff options
Diffstat (limited to 'drivers/staging/android/binder.c')
| -rw-r--r-- | drivers/staging/android/binder.c | 337 | 
1 files changed, 205 insertions, 132 deletions
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 98ac020bf91..a741da77828 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -118,6 +118,7 @@ static int binder_set_stop_on_user_error(const char *val,  					 struct kernel_param *kp)  {  	int ret; +  	ret = param_set_int(val, kp);  	if (binder_stop_on_user_error < 2)  		wake_up(&binder_user_error_wait); @@ -194,6 +195,7 @@ static struct binder_transaction_log_entry *binder_transaction_log_add(  	struct binder_transaction_log *log)  {  	struct binder_transaction_log_entry *e; +  	e = &log->entry[log->next];  	memset(e, 0, sizeof(*e));  	log->next++; @@ -228,8 +230,8 @@ struct binder_node {  	int internal_strong_refs;  	int local_weak_refs;  	int local_strong_refs; -	void __user *ptr; -	void __user *cookie; +	binder_uintptr_t ptr; +	binder_uintptr_t cookie;  	unsigned has_strong_ref:1;  	unsigned pending_strong_ref:1;  	unsigned has_weak_ref:1; @@ -242,7 +244,7 @@ struct binder_node {  struct binder_ref_death {  	struct binder_work work; -	void __user *cookie; +	binder_uintptr_t cookie;  };  struct binder_ref { @@ -432,16 +434,17 @@ static inline void binder_unlock(const char *tag)  static void binder_set_nice(long nice)  {  	long min_nice; +  	if (can_nice(current, nice)) {  		set_user_nice(current, nice);  		return;  	} -	min_nice = 20 - current->signal->rlim[RLIMIT_NICE].rlim_cur; +	min_nice = rlimit_to_nice(current->signal->rlim[RLIMIT_NICE].rlim_cur);  	binder_debug(BINDER_DEBUG_PRIORITY_CAP,  		     "%d: nice value %ld not allowed use %ld instead\n",  		      current->pid, nice, min_nice);  	set_user_nice(current, min_nice); -	if (min_nice < 20) +	if (min_nice <= MAX_NICE)  		return;  	binder_user_error("%d RLIMIT_NICE not set\n", current->pid);  } @@ -515,14 +518,14 @@ static void binder_insert_allocated_buffer(struct binder_proc *proc,  }  static struct binder_buffer *binder_buffer_lookup(struct binder_proc *proc, -						  void __user *user_ptr) +						  uintptr_t user_ptr)  {  	struct rb_node *n = proc->allocated_buffers.rb_node;  	struct binder_buffer *buffer;  	struct binder_buffer *kern_ptr; -	kern_ptr = user_ptr - proc->user_buffer_offset -		- offsetof(struct binder_buffer, data); +	kern_ptr = (struct binder_buffer *)(user_ptr - proc->user_buffer_offset +		- offsetof(struct binder_buffer, data));  	while (n) {  		buffer = rb_entry(n, struct binder_buffer, rb_node); @@ -584,6 +587,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,  	for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) {  		int ret;  		struct page **page_array_ptr; +  		page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];  		BUG_ON(*page); @@ -726,6 +730,7 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,  	binder_insert_allocated_buffer(proc, buffer);  	if (buffer_size != size) {  		struct binder_buffer *new_buffer = (void *)buffer->data + size; +  		list_add(&new_buffer->entry, &buffer->entry);  		new_buffer->free = 1;  		binder_insert_free_buffer(proc, new_buffer); @@ -838,6 +843,7 @@ static void binder_free_buf(struct binder_proc *proc,  	if (!list_is_last(&buffer->entry, &proc->buffers)) {  		struct binder_buffer *next = list_entry(buffer->entry.next,  						struct binder_buffer, entry); +  		if (next->free) {  			rb_erase(&next->rb_node, &proc->free_buffers);  			binder_delete_free_buffer(proc, next); @@ -846,6 +852,7 @@ static void binder_free_buf(struct binder_proc *proc,  	if (proc->buffers.next != &buffer->entry) {  		struct binder_buffer *prev = list_entry(buffer->entry.prev,  						struct binder_buffer, entry); +  		if (prev->free) {  			binder_delete_free_buffer(proc, buffer);  			rb_erase(&prev->rb_node, &proc->free_buffers); @@ -856,7 +863,7 @@ static void binder_free_buf(struct binder_proc *proc,  }  static struct binder_node *binder_get_node(struct binder_proc *proc, -					   void __user *ptr) +					   binder_uintptr_t ptr)  {  	struct rb_node *n = proc->nodes.rb_node;  	struct binder_node *node; @@ -875,8 +882,8 @@ static struct binder_node *binder_get_node(struct binder_proc *proc,  }  static struct binder_node *binder_new_node(struct binder_proc *proc, -					   void __user *ptr, -					   void __user *cookie) +					   binder_uintptr_t ptr, +					   binder_uintptr_t cookie)  {  	struct rb_node **p = &proc->nodes.rb_node;  	struct rb_node *parent = NULL; @@ -908,9 +915,9 @@ static struct binder_node *binder_new_node(struct binder_proc *proc,  	INIT_LIST_HEAD(&node->work.entry);  	INIT_LIST_HEAD(&node->async_todo);  	binder_debug(BINDER_DEBUG_INTERNAL_REFS, -		     "%d:%d node %d u%p c%p created\n", +		     "%d:%d node %d u%016llx c%016llx created\n",  		     proc->pid, current->pid, node->debug_id, -		     node->ptr, node->cookie); +		     (u64)node->ptr, (u64)node->cookie);  	return node;  } @@ -1107,6 +1114,7 @@ static int binder_inc_ref(struct binder_ref *ref, int strong,  			  struct list_head *target_list)  {  	int ret; +  	if (strong) {  		if (ref->strong == 0) {  			ret = binder_inc_node(ref->node, 1, 1, target_list); @@ -1138,6 +1146,7 @@ static int binder_dec_ref(struct binder_ref *ref, int strong)  		ref->strong--;  		if (ref->strong == 0) {  			int ret; +  			ret = binder_dec_node(ref->node, strong, 1);  			if (ret)  				return ret; @@ -1177,6 +1186,7 @@ static void binder_send_failed_reply(struct binder_transaction *t,  				     uint32_t error_code)  {  	struct binder_thread *target_thread; +  	BUG_ON(t->flags & TF_ONE_WAY);  	while (1) {  		target_thread = t->from; @@ -1226,9 +1236,9 @@ static void binder_send_failed_reply(struct binder_transaction *t,  static void binder_transaction_buffer_release(struct binder_proc *proc,  					      struct binder_buffer *buffer, -					      size_t *failed_at) +					      binder_size_t *failed_at)  { -	size_t *offp, *off_end; +	binder_size_t *offp, *off_end;  	int debug_id = buffer->debug_id;  	binder_debug(BINDER_DEBUG_TRANSACTION, @@ -1239,18 +1249,20 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,  	if (buffer->target_node)  		binder_dec_node(buffer->target_node, 1, 0); -	offp = (size_t *)(buffer->data + ALIGN(buffer->data_size, sizeof(void *))); +	offp = (binder_size_t *)(buffer->data + +				 ALIGN(buffer->data_size, sizeof(void *)));  	if (failed_at)  		off_end = failed_at;  	else  		off_end = (void *)offp + buffer->offsets_size;  	for (; offp < off_end; offp++) {  		struct flat_binder_object *fp; +  		if (*offp > buffer->data_size - sizeof(*fp) ||  		    buffer->data_size < sizeof(*fp) ||  		    !IS_ALIGNED(*offp, sizeof(u32))) { -			pr_err("transaction release %d bad offset %zd, size %zd\n", -			 debug_id, *offp, buffer->data_size); +			pr_err("transaction release %d bad offset %lld, size %zd\n", +			       debug_id, (u64)*offp, buffer->data_size);  			continue;  		}  		fp = (struct flat_binder_object *)(buffer->data + *offp); @@ -1258,19 +1270,21 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,  		case BINDER_TYPE_BINDER:  		case BINDER_TYPE_WEAK_BINDER: {  			struct binder_node *node = binder_get_node(proc, fp->binder); +  			if (node == NULL) { -				pr_err("transaction release %d bad node %p\n", -					debug_id, fp->binder); +				pr_err("transaction release %d bad node %016llx\n", +				       debug_id, (u64)fp->binder);  				break;  			}  			binder_debug(BINDER_DEBUG_TRANSACTION, -				     "        node %d u%p\n", -				     node->debug_id, node->ptr); +				     "        node %d u%016llx\n", +				     node->debug_id, (u64)node->ptr);  			binder_dec_node(node, fp->type == BINDER_TYPE_BINDER, 0);  		} break;  		case BINDER_TYPE_HANDLE:  		case BINDER_TYPE_WEAK_HANDLE: {  			struct binder_ref *ref = binder_get_ref(proc, fp->handle); +  			if (ref == NULL) {  				pr_err("transaction release %d bad handle %d\n",  				 debug_id, fp->handle); @@ -1303,7 +1317,7 @@ static void binder_transaction(struct binder_proc *proc,  {  	struct binder_transaction *t;  	struct binder_work *tcomplete; -	size_t *offp, *off_end; +	binder_size_t *offp, *off_end;  	struct binder_proc *target_proc;  	struct binder_thread *target_thread = NULL;  	struct binder_node *target_node = NULL; @@ -1362,6 +1376,7 @@ static void binder_transaction(struct binder_proc *proc,  	} else {  		if (tr->target.handle) {  			struct binder_ref *ref; +  			ref = binder_get_ref(proc, tr->target.handle);  			if (ref == NULL) {  				binder_user_error("%d:%d got transaction to invalid handle\n", @@ -1385,6 +1400,7 @@ static void binder_transaction(struct binder_proc *proc,  		}  		if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) {  			struct binder_transaction *tmp; +  			tmp = thread->transaction_stack;  			if (tmp->to_thread != thread) {  				binder_user_error("%d:%d got new transaction with bad transaction stack, transaction %d has target %d:%d\n", @@ -1432,24 +1448,26 @@ static void binder_transaction(struct binder_proc *proc,  	if (reply)  		binder_debug(BINDER_DEBUG_TRANSACTION, -			     "%d:%d BC_REPLY %d -> %d:%d, data %p-%p size %zd-%zd\n", +			     "%d:%d BC_REPLY %d -> %d:%d, data %016llx-%016llx size %lld-%lld\n",  			     proc->pid, thread->pid, t->debug_id,  			     target_proc->pid, target_thread->pid, -			     tr->data.ptr.buffer, tr->data.ptr.offsets, -			     tr->data_size, tr->offsets_size); +			     (u64)tr->data.ptr.buffer, +			     (u64)tr->data.ptr.offsets, +			     (u64)tr->data_size, (u64)tr->offsets_size);  	else  		binder_debug(BINDER_DEBUG_TRANSACTION, -			     "%d:%d BC_TRANSACTION %d -> %d - node %d, data %p-%p size %zd-%zd\n", +			     "%d:%d BC_TRANSACTION %d -> %d - node %d, data %016llx-%016llx size %lld-%lld\n",  			     proc->pid, thread->pid, t->debug_id,  			     target_proc->pid, target_node->debug_id, -			     tr->data.ptr.buffer, tr->data.ptr.offsets, -			     tr->data_size, tr->offsets_size); +			     (u64)tr->data.ptr.buffer, +			     (u64)tr->data.ptr.offsets, +			     (u64)tr->data_size, (u64)tr->offsets_size);  	if (!reply && !(tr->flags & TF_ONE_WAY))  		t->from = thread;  	else  		t->from = NULL; -	t->sender_euid = proc->tsk->cred->euid; +	t->sender_euid = task_euid(proc->tsk);  	t->to_proc = target_proc;  	t->to_thread = target_thread;  	t->code = tr->code; @@ -1472,34 +1490,38 @@ static void binder_transaction(struct binder_proc *proc,  	if (target_node)  		binder_inc_node(target_node, 1, 0, NULL); -	offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *))); +	offp = (binder_size_t *)(t->buffer->data + +				 ALIGN(tr->data_size, sizeof(void *))); -	if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) { +	if (copy_from_user(t->buffer->data, (const void __user *)(uintptr_t) +			   tr->data.ptr.buffer, tr->data_size)) {  		binder_user_error("%d:%d got transaction with invalid data ptr\n",  				proc->pid, thread->pid);  		return_error = BR_FAILED_REPLY;  		goto err_copy_data_failed;  	} -	if (copy_from_user(offp, tr->data.ptr.offsets, tr->offsets_size)) { +	if (copy_from_user(offp, (const void __user *)(uintptr_t) +			   tr->data.ptr.offsets, tr->offsets_size)) {  		binder_user_error("%d:%d got transaction with invalid offsets ptr\n",  				proc->pid, thread->pid);  		return_error = BR_FAILED_REPLY;  		goto err_copy_data_failed;  	} -	if (!IS_ALIGNED(tr->offsets_size, sizeof(size_t))) { -		binder_user_error("%d:%d got transaction with invalid offsets size, %zd\n", -				proc->pid, thread->pid, tr->offsets_size); +	if (!IS_ALIGNED(tr->offsets_size, sizeof(binder_size_t))) { +		binder_user_error("%d:%d got transaction with invalid offsets size, %lld\n", +				proc->pid, thread->pid, (u64)tr->offsets_size);  		return_error = BR_FAILED_REPLY;  		goto err_bad_offset;  	}  	off_end = (void *)offp + tr->offsets_size;  	for (; offp < off_end; offp++) {  		struct flat_binder_object *fp; +  		if (*offp > t->buffer->data_size - sizeof(*fp) ||  		    t->buffer->data_size < sizeof(*fp) ||  		    !IS_ALIGNED(*offp, sizeof(u32))) { -			binder_user_error("%d:%d got transaction with invalid offset, %zd\n", -					proc->pid, thread->pid, *offp); +			binder_user_error("%d:%d got transaction with invalid offset, %lld\n", +					  proc->pid, thread->pid, (u64)*offp);  			return_error = BR_FAILED_REPLY;  			goto err_bad_offset;  		} @@ -1509,6 +1531,7 @@ static void binder_transaction(struct binder_proc *proc,  		case BINDER_TYPE_WEAK_BINDER: {  			struct binder_ref *ref;  			struct binder_node *node = binder_get_node(proc, fp->binder); +  			if (node == NULL) {  				node = binder_new_node(proc, fp->binder, fp->cookie);  				if (node == NULL) { @@ -1519,10 +1542,11 @@ static void binder_transaction(struct binder_proc *proc,  				node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);  			}  			if (fp->cookie != node->cookie) { -				binder_user_error("%d:%d sending u%p node %d, cookie mismatch %p != %p\n", +				binder_user_error("%d:%d sending u%016llx node %d, cookie mismatch %016llx != %016llx\n",  					proc->pid, thread->pid, -					fp->binder, node->debug_id, -					fp->cookie, node->cookie); +					(u64)fp->binder, node->debug_id, +					(u64)fp->cookie, (u64)node->cookie); +				return_error = BR_FAILED_REPLY;  				goto err_binder_get_ref_for_node_failed;  			}  			ref = binder_get_ref_for_node(target_proc, node); @@ -1540,13 +1564,14 @@ static void binder_transaction(struct binder_proc *proc,  			trace_binder_transaction_node_to_ref(t, node, ref);  			binder_debug(BINDER_DEBUG_TRANSACTION, -				     "        node %d u%p -> ref %d desc %d\n", -				     node->debug_id, node->ptr, ref->debug_id, -				     ref->desc); +				     "        node %d u%016llx -> ref %d desc %d\n", +				     node->debug_id, (u64)node->ptr, +				     ref->debug_id, ref->desc);  		} break;  		case BINDER_TYPE_HANDLE:  		case BINDER_TYPE_WEAK_HANDLE: {  			struct binder_ref *ref = binder_get_ref(proc, fp->handle); +  			if (ref == NULL) {  				binder_user_error("%d:%d got transaction with invalid handle, %d\n",  						proc->pid, @@ -1564,11 +1589,12 @@ static void binder_transaction(struct binder_proc *proc,  				binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);  				trace_binder_transaction_ref_to_node(t, ref);  				binder_debug(BINDER_DEBUG_TRANSACTION, -					     "        ref %d desc %d -> node %d u%p\n", +					     "        ref %d desc %d -> node %d u%016llx\n",  					     ref->debug_id, ref->desc, ref->node->debug_id, -					     ref->node->ptr); +					     (u64)ref->node->ptr);  			} else {  				struct binder_ref *new_ref; +  				new_ref = binder_get_ref_for_node(target_proc, ref->node);  				if (new_ref == NULL) {  					return_error = BR_FAILED_REPLY; @@ -1682,12 +1708,13 @@ err_dead_binder:  err_invalid_target_handle:  err_no_context_mgr_node:  	binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, -		     "%d:%d transaction failed %d, size %zd-%zd\n", +		     "%d:%d transaction failed %d, size %lld-%lld\n",  		     proc->pid, thread->pid, return_error, -		     tr->data_size, tr->offsets_size); +		     (u64)tr->data_size, (u64)tr->offsets_size);  	{  		struct binder_transaction_log_entry *fe; +  		fe = binder_transaction_log_add(&binder_transaction_log_failed);  		*fe = *e;  	} @@ -1700,10 +1727,13 @@ err_no_context_mgr_node:  		thread->return_error = return_error;  } -int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, -			void __user *buffer, size_t size, size_t *consumed) +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)  {  	uint32_t cmd; +	void __user *buffer = (void __user *)(uintptr_t)binder_buffer;  	void __user *ptr = buffer + *consumed;  	void __user *end = buffer + size; @@ -1772,33 +1802,33 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,  		}  		case BC_INCREFS_DONE:  		case BC_ACQUIRE_DONE: { -			void __user *node_ptr; -			void *cookie; +			binder_uintptr_t node_ptr; +			binder_uintptr_t cookie;  			struct binder_node *node; -			if (get_user(node_ptr, (void * __user *)ptr)) +			if (get_user(node_ptr, (binder_uintptr_t __user *)ptr))  				return -EFAULT; -			ptr += sizeof(void *); -			if (get_user(cookie, (void * __user *)ptr)) +			ptr += sizeof(binder_uintptr_t); +			if (get_user(cookie, (binder_uintptr_t __user *)ptr))  				return -EFAULT; -			ptr += sizeof(void *); +			ptr += sizeof(binder_uintptr_t);  			node = binder_get_node(proc, node_ptr);  			if (node == NULL) { -				binder_user_error("%d:%d %s u%p no match\n", +				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", -					node_ptr); +					(u64)node_ptr);  				break;  			}  			if (cookie != node->cookie) { -				binder_user_error("%d:%d %s u%p node %d cookie mismatch %p != %p\n", +				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", -					node_ptr, node->debug_id, -					cookie, node->cookie); +					(u64)node_ptr, node->debug_id, +					(u64)cookie, (u64)node->cookie);  				break;  			}  			if (cmd == BC_ACQUIRE_DONE) { @@ -1834,27 +1864,28 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,  			return -EINVAL;  		case BC_FREE_BUFFER: { -			void __user *data_ptr; +			binder_uintptr_t data_ptr;  			struct binder_buffer *buffer; -			if (get_user(data_ptr, (void * __user *)ptr)) +			if (get_user(data_ptr, (binder_uintptr_t __user *)ptr))  				return -EFAULT; -			ptr += sizeof(void *); +			ptr += sizeof(binder_uintptr_t);  			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); +				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%p matched unreturned buffer\n", -					proc->pid, thread->pid, data_ptr); +				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%p found buffer %d for %s transaction\n", -				     proc->pid, thread->pid, data_ptr, buffer->debug_id, +				     "%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) { @@ -1924,16 +1955,16 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,  		case BC_REQUEST_DEATH_NOTIFICATION:  		case BC_CLEAR_DEATH_NOTIFICATION: {  			uint32_t target; -			void __user *cookie; +			binder_uintptr_t 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)) +			if (get_user(cookie, (binder_uintptr_t __user *)ptr))  				return -EFAULT; -			ptr += sizeof(void *); +			ptr += sizeof(binder_uintptr_t);  			ref = binder_get_ref(proc, target);  			if (ref == NULL) {  				binder_user_error("%d:%d %s invalid ref %d\n", @@ -1946,12 +1977,12 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,  			}  			binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION, -				     "%d:%d %s %p ref %d desc %d s %d w %d for node %d\n", +				     "%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", -				     cookie, ref->debug_id, ref->desc, +				     (u64)cookie, ref->debug_id, ref->desc,  				     ref->strong, ref->weak, ref->node->debug_id);  			if (cmd == BC_REQUEST_DEATH_NOTIFICATION) { @@ -1989,9 +2020,10 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,  				}  				death = ref->death;  				if (death->cookie != cookie) { -					binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch %p != %p\n", +					binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch %016llx != %016llx\n",  						proc->pid, thread->pid, -						death->cookie, cookie); +						(u64)death->cookie, +						(u64)cookie);  					break;  				}  				ref->death = NULL; @@ -2011,25 +2043,28 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,  		} break;  		case BC_DEAD_BINDER_DONE: {  			struct binder_work *w; -			void __user *cookie; +			binder_uintptr_t cookie;  			struct binder_ref_death *death = NULL; -			if (get_user(cookie, (void __user * __user *)ptr)) + +			if (get_user(cookie, (binder_uintptr_t __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;  				}  			}  			binder_debug(BINDER_DEBUG_DEAD_BINDER, -				     "%d:%d BC_DEAD_BINDER_DONE %p found %p\n", -				     proc->pid, thread->pid, cookie, death); +				     "%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 %p not found\n", -					proc->pid, thread->pid, cookie); +				binder_user_error("%d:%d BC_DEAD_BINDER_DONE %016llx not found\n", +					proc->pid, thread->pid, (u64)cookie);  				break;  			} @@ -2055,8 +2090,8 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,  	return 0;  } -void binder_stat_br(struct binder_proc *proc, struct binder_thread *thread, -		    uint32_t cmd) +static void binder_stat_br(struct binder_proc *proc, +			   struct binder_thread *thread, uint32_t cmd)  {  	trace_binder_return(cmd);  	if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.br)) { @@ -2081,9 +2116,10 @@ static int binder_has_thread_work(struct binder_thread *thread)  static int binder_thread_read(struct binder_proc *proc,  			      struct binder_thread *thread, -			      void  __user *buffer, size_t size, -			      size_t *consumed, int non_block) +			      binder_uintptr_t binder_buffer, size_t size, +			      binder_size_t *consumed, int non_block)  { +	void __user *buffer = (void __user *)(uintptr_t)binder_buffer;  	void __user *ptr = buffer + *consumed;  	void __user *end = buffer + size; @@ -2203,6 +2239,7 @@ retry:  			const char *cmd_name;  			int strong = node->internal_strong_refs || node->local_strong_refs;  			int weak = !hlist_empty(&node->refs) || node->local_weak_refs || strong; +  			if (weak && !node->has_weak_ref) {  				cmd = BR_INCREFS;  				cmd_name = "BR_INCREFS"; @@ -2228,32 +2265,40 @@ retry:  				if (put_user(cmd, (uint32_t __user *)ptr))  					return -EFAULT;  				ptr += sizeof(uint32_t); -				if (put_user(node->ptr, (void * __user *)ptr)) +				if (put_user(node->ptr, +					     (binder_uintptr_t __user *)ptr))  					return -EFAULT; -				ptr += sizeof(void *); -				if (put_user(node->cookie, (void * __user *)ptr)) +				ptr += sizeof(binder_uintptr_t); +				if (put_user(node->cookie, +					     (binder_uintptr_t __user *)ptr))  					return -EFAULT; -				ptr += sizeof(void *); +				ptr += sizeof(binder_uintptr_t);  				binder_stat_br(proc, thread, cmd);  				binder_debug(BINDER_DEBUG_USER_REFS, -					     "%d:%d %s %d u%p c%p\n", -					     proc->pid, thread->pid, cmd_name, node->debug_id, node->ptr, node->cookie); +					     "%d:%d %s %d u%016llx c%016llx\n", +					     proc->pid, thread->pid, cmd_name, +					     node->debug_id, +					     (u64)node->ptr, (u64)node->cookie);  			} else {  				list_del_init(&w->entry);  				if (!weak && !strong) {  					binder_debug(BINDER_DEBUG_INTERNAL_REFS, -						     "%d:%d node %d u%p c%p deleted\n", -						     proc->pid, thread->pid, node->debug_id, -						     node->ptr, node->cookie); +						     "%d:%d node %d u%016llx c%016llx deleted\n", +						     proc->pid, thread->pid, +						     node->debug_id, +						     (u64)node->ptr, +						     (u64)node->cookie);  					rb_erase(&node->rb_node, &proc->nodes);  					kfree(node);  					binder_stats_deleted(BINDER_STAT_NODE);  				} else {  					binder_debug(BINDER_DEBUG_INTERNAL_REFS, -						     "%d:%d node %d u%p c%p state unchanged\n", -						     proc->pid, thread->pid, node->debug_id, node->ptr, -						     node->cookie); +						     "%d:%d node %d u%016llx c%016llx state unchanged\n", +						     proc->pid, thread->pid, +						     node->debug_id, +						     (u64)node->ptr, +						     (u64)node->cookie);  				}  			}  		} break; @@ -2271,17 +2316,18 @@ retry:  			if (put_user(cmd, (uint32_t __user *)ptr))  				return -EFAULT;  			ptr += sizeof(uint32_t); -			if (put_user(death->cookie, (void * __user *)ptr)) +			if (put_user(death->cookie, +				     (binder_uintptr_t __user *)ptr))  				return -EFAULT; -			ptr += sizeof(void *); +			ptr += sizeof(binder_uintptr_t);  			binder_stat_br(proc, thread, cmd);  			binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION, -				     "%d:%d %s %p\n", +				     "%d:%d %s %016llx\n",  				      proc->pid, thread->pid,  				      cmd == BR_DEAD_BINDER ?  				      "BR_DEAD_BINDER" :  				      "BR_CLEAR_DEATH_NOTIFICATION_DONE", -				      death->cookie); +				      (u64)death->cookie);  			if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) {  				list_del(&w->entry); @@ -2300,6 +2346,7 @@ retry:  		BUG_ON(t->buffer == NULL);  		if (t->buffer->target_node) {  			struct binder_node *target_node = t->buffer->target_node; +  			tr.target.ptr = target_node->ptr;  			tr.cookie =  target_node->cookie;  			t->saved_priority = task_nice(current); @@ -2311,8 +2358,8 @@ retry:  				binder_set_nice(target_node->min_priority);  			cmd = BR_TRANSACTION;  		} else { -			tr.target.ptr = NULL; -			tr.cookie = NULL; +			tr.target.ptr = 0; +			tr.cookie = 0;  			cmd = BR_REPLY;  		}  		tr.code = t->code; @@ -2321,6 +2368,7 @@ retry:  		if (t->from) {  			struct task_struct *sender = t->from->proc->tsk; +  			tr.sender_pid = task_tgid_nr_ns(sender,  							task_active_pid_ns(current));  		} else { @@ -2329,8 +2377,9 @@ retry:  		tr.data_size = t->buffer->data_size;  		tr.offsets_size = t->buffer->offsets_size; -		tr.data.ptr.buffer = (void *)t->buffer->data + -					proc->user_buffer_offset; +		tr.data.ptr.buffer = (binder_uintptr_t)( +					(uintptr_t)t->buffer->data + +					proc->user_buffer_offset);  		tr.data.ptr.offsets = tr.data.ptr.buffer +  					ALIGN(t->buffer->data_size,  					    sizeof(void *)); @@ -2345,14 +2394,14 @@ retry:  		trace_binder_transaction_received(t);  		binder_stat_br(proc, thread, cmd);  		binder_debug(BINDER_DEBUG_TRANSACTION, -			     "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %p-%p\n", +			     "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %016llx-%016llx\n",  			     proc->pid, thread->pid,  			     (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" :  			     "BR_REPLY",  			     t->debug_id, t->from ? t->from->proc->pid : 0,  			     t->from ? t->from->pid : 0, cmd,  			     t->buffer->data_size, t->buffer->offsets_size, -			     tr.data.ptr.buffer, tr.data.ptr.offsets); +			     (u64)tr.data.ptr.buffer, (u64)tr.data.ptr.offsets);  		list_del(&t->work.entry);  		t->buffer->allow_user_free = 1; @@ -2390,6 +2439,7 @@ done:  static void binder_release_work(struct list_head *list)  {  	struct binder_work *w; +  	while (!list_empty(list)) {  		w = list_first_entry(list, struct binder_work, entry);  		list_del_init(&w->entry); @@ -2422,8 +2472,8 @@ static void binder_release_work(struct list_head *list)  			death = container_of(w, struct binder_ref_death, work);  			binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, -				"undelivered death notification, %p\n", -				death->cookie); +				"undelivered death notification, %016llx\n", +				(u64)death->cookie);  			kfree(death);  			binder_stats_deleted(BINDER_STAT_DEATH);  		} break; @@ -2551,6 +2601,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  	struct binder_thread *thread;  	unsigned int size = _IOC_SIZE(cmd);  	void __user *ubuf = (void __user *)arg; +	kuid_t curr_euid = current_euid();  	/*pr_info("binder_ioctl: %d:%d %x %lx\n", proc->pid, current->pid, cmd, arg);*/ @@ -2570,6 +2621,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  	switch (cmd) {  	case BINDER_WRITE_READ: {  		struct binder_write_read bwr; +  		if (size != sizeof(struct binder_write_read)) {  			ret = -EINVAL;  			goto err; @@ -2579,12 +2631,16 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  			goto err;  		}  		binder_debug(BINDER_DEBUG_READ_WRITE, -			     "%d:%d write %zd at %016lx, read %zd at %016lx\n", -			     proc->pid, thread->pid, bwr.write_size, -			     bwr.write_buffer, bwr.read_size, bwr.read_buffer); +			     "%d:%d write %lld at %016llx, read %lld at %016llx\n", +			     proc->pid, thread->pid, +			     (u64)bwr.write_size, (u64)bwr.write_buffer, +			     (u64)bwr.read_size, (u64)bwr.read_buffer);  		if (bwr.write_size > 0) { -			ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed); +			ret = binder_thread_write(proc, thread, +						  bwr.write_buffer, +						  bwr.write_size, +						  &bwr.write_consumed);  			trace_binder_write_done(ret);  			if (ret < 0) {  				bwr.read_consumed = 0; @@ -2594,7 +2650,10 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  			}  		}  		if (bwr.read_size > 0) { -			ret = binder_thread_read(proc, thread, (void __user *)bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK); +			ret = binder_thread_read(proc, thread, bwr.read_buffer, +						 bwr.read_size, +						 &bwr.read_consumed, +						 filp->f_flags & O_NONBLOCK);  			trace_binder_read_done(ret);  			if (!list_empty(&proc->todo))  				wake_up_interruptible(&proc->wait); @@ -2605,9 +2664,10 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  			}  		}  		binder_debug(BINDER_DEBUG_READ_WRITE, -			     "%d:%d wrote %zd of %zd, read return %zd of %zd\n", -			     proc->pid, thread->pid, bwr.write_consumed, bwr.write_size, -			     bwr.read_consumed, bwr.read_size); +			     "%d:%d wrote %lld of %lld, read return %lld of %lld\n", +			     proc->pid, thread->pid, +			     (u64)bwr.write_consumed, (u64)bwr.write_size, +			     (u64)bwr.read_consumed, (u64)bwr.read_size);  		if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {  			ret = -EFAULT;  			goto err; @@ -2627,16 +2687,17 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  			goto err;  		}  		if (uid_valid(binder_context_mgr_uid)) { -			if (!uid_eq(binder_context_mgr_uid, current->cred->euid)) { +			if (!uid_eq(binder_context_mgr_uid, curr_euid)) {  				pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n", -				       from_kuid(&init_user_ns, current->cred->euid), +				       from_kuid(&init_user_ns, curr_euid),  				       from_kuid(&init_user_ns, binder_context_mgr_uid));  				ret = -EPERM;  				goto err;  			} -		} else -			binder_context_mgr_uid = current->cred->euid; -		binder_context_mgr_node = binder_new_node(proc, NULL, NULL); +		} else { +			binder_context_mgr_uid = curr_euid; +		} +		binder_context_mgr_node = binder_new_node(proc, 0, 0);  		if (binder_context_mgr_node == NULL) {  			ret = -ENOMEM;  			goto err; @@ -2652,16 +2713,20 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  		binder_free_thread(proc, thread);  		thread = NULL;  		break; -	case BINDER_VERSION: +	case BINDER_VERSION: { +		struct binder_version __user *ver = ubuf; +  		if (size != sizeof(struct binder_version)) {  			ret = -EINVAL;  			goto err;  		} -		if (put_user(BINDER_CURRENT_PROTOCOL_VERSION, &((struct binder_version *)ubuf)->protocol_version)) { +		if (put_user(BINDER_CURRENT_PROTOCOL_VERSION, +			     &ver->protocol_version)) {  			ret = -EINVAL;  			goto err;  		}  		break; +	}  	default:  		ret = -EINVAL;  		goto err; @@ -2682,6 +2747,7 @@ err_unlocked:  static void binder_vma_open(struct vm_area_struct *vma)  {  	struct binder_proc *proc = vma->vm_private_data; +  	binder_debug(BINDER_DEBUG_OPEN_CLOSE,  		     "%d open vm area %lx-%lx (%ld K) vma %lx pagep %lx\n",  		     proc->pid, vma->vm_start, vma->vm_end, @@ -2692,6 +2758,7 @@ static void binder_vma_open(struct vm_area_struct *vma)  static void binder_vma_close(struct vm_area_struct *vma)  {  	struct binder_proc *proc = vma->vm_private_data; +  	binder_debug(BINDER_DEBUG_OPEN_CLOSE,  		     "%d close vm area %lx-%lx (%ld K) vma %lx pagep %lx\n",  		     proc->pid, vma->vm_start, vma->vm_end, @@ -2834,6 +2901,7 @@ static int binder_open(struct inode *nodp, struct file *filp)  	if (binder_debugfs_dir_entry_proc) {  		char strbuf[11]; +  		snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);  		proc->debugfs_entry = debugfs_create_file(strbuf, S_IRUGO,  			binder_debugfs_dir_entry_proc, proc, &binder_proc_fops); @@ -2855,8 +2923,10 @@ static void binder_deferred_flush(struct binder_proc *proc)  {  	struct rb_node *n;  	int wake_count = 0; +  	for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) {  		struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node); +  		thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN;  		if (thread->looper & BINDER_LOOPER_STATE_WAITING) {  			wake_up_interruptible(&thread->wait); @@ -2873,6 +2943,7 @@ static void binder_deferred_flush(struct binder_proc *proc)  static int binder_release(struct inode *nodp, struct file *filp)  {  	struct binder_proc *proc = filp->private_data; +  	debugfs_remove(proc->debugfs_entry);  	binder_defer_work(proc, BINDER_DEFERRED_RELEASE); @@ -2903,7 +2974,7 @@ static int binder_node_release(struct binder_node *node, int refs)  		refs++;  		if (!ref->death) -			goto out; +			continue;  		death++; @@ -2916,7 +2987,6 @@ static int binder_node_release(struct binder_node *node, int refs)  			BUG();  	} -out:  	binder_debug(BINDER_DEBUG_DEAD_BINDER,  		     "node %d now dead, refs %d, death %d\n",  		     node->debug_id, refs, death); @@ -3035,6 +3105,7 @@ static void binder_deferred_func(struct work_struct *work)  	struct files_struct *files;  	int defer; +  	do {  		binder_lock(__func__);  		mutex_lock(&binder_deferred_lock); @@ -3132,8 +3203,9 @@ static void print_binder_work(struct seq_file *m, const char *prefix,  		break;  	case BINDER_WORK_NODE:  		node = container_of(w, struct binder_node, work); -		seq_printf(m, "%snode work %d: u%p c%p\n", -			   prefix, node->debug_id, node->ptr, node->cookie); +		seq_printf(m, "%snode work %d: u%016llx c%016llx\n", +			   prefix, node->debug_id, +			   (u64)node->ptr, (u64)node->cookie);  		break;  	case BINDER_WORK_DEAD_BINDER:  		seq_printf(m, "%shas dead binder\n", prefix); @@ -3193,8 +3265,8 @@ static void print_binder_node(struct seq_file *m, struct binder_node *node)  	hlist_for_each_entry(ref, &node->refs, node_entry)  		count++; -	seq_printf(m, "  node %d: u%p c%p hs %d hw %d ls %d lw %d is %d iw %d", -		   node->debug_id, node->ptr, node->cookie, +	seq_printf(m, "  node %d: u%016llx c%016llx hs %d hw %d ls %d lw %d is %d iw %d", +		   node->debug_id, (u64)node->ptr, (u64)node->cookie,  		   node->has_strong_ref, node->has_weak_ref,  		   node->local_strong_refs, node->local_weak_refs,  		   node->internal_strong_refs, count); @@ -3496,6 +3568,7 @@ static const struct file_operations binder_fops = {  	.owner = THIS_MODULE,  	.poll = binder_poll,  	.unlocked_ioctl = binder_ioctl, +	.compat_ioctl = binder_ioctl,  	.mmap = binder_mmap,  	.open = binder_open,  	.flush = binder_flush,  | 
