⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 binder.c

📁 for binder and can be set as any mode
💻 C
📖 第 1 页 / 共 5 页
字号:
			}		}	}	if (target_thread) {		e->to_thread = target_thread->pid;		target_list = &target_thread->todo;		target_wait = &target_thread->wait;	} else {		target_list = &target_proc->todo;		target_wait = &target_proc->wait;	}	e->to_proc = target_proc->pid;	/* TODO: reuse incoming transaction for reply */	t = kzalloc(sizeof(*t), GFP_KERNEL);	if (t == NULL) {		return_error = BR_FAILED_REPLY;		goto err_alloc_t_failed;	}	binder_stats.obj_created[BINDER_STAT_TRANSACTION]++;	tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);	if (tcomplete == NULL) {		return_error = BR_FAILED_REPLY;		goto err_alloc_tcomplete_failed;	}	binder_stats.obj_created[BINDER_STAT_TRANSACTION_COMPLETE]++;	t->debug_id = ++binder_last_id;	e->debug_id = t->debug_id;	if (binder_debug_mask & BINDER_DEBUG_TRANSACTION) {		if (reply)			printk(KERN_INFO "binder: %d:%d BC_REPLY %d -> %d:%d, "			       "data %p-%p size %d-%d\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);		else			printk(KERN_INFO "binder: %d:%d BC_TRANSACTION %d -> "			       "%d - node %d, data %p-%p size %d-%d\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);	}	if (!reply && !(tr->flags & TF_ONE_WAY))		t->from = thread;	else		t->from = NULL;	t->sender_euid = proc->tsk->euid;	t->to_proc = target_proc;	t->to_thread = target_thread;	t->code = tr->code;	t->flags = tr->flags;	t->priority = task_nice(current);	t->buffer = binder_alloc_buf(target_proc, tr->data_size,		tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));	if (t->buffer == NULL) {		return_error = BR_FAILED_REPLY;		goto err_binder_alloc_buf_failed;	}	t->buffer->allow_user_free = 0;	t->buffer->debug_id = t->debug_id;	t->buffer->transaction = t;	t->buffer->target_node = target_node;	if (target_node)		binder_inc_node(target_node, 1, 0, NULL);	offp = (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)) {		binder_user_error("binder: %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)) {		binder_user_error("binder: %d:%d got transaction with invalid "			"offsets ptr\n", proc->pid, thread->pid);		return_error = BR_FAILED_REPLY;		goto err_copy_data_failed;	}	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)) {			binder_user_error("binder: %d:%d got transaction with "				"invalid offset, %d\n",				proc->pid, thread->pid, *offp);			return_error = BR_FAILED_REPLY;			goto err_bad_offset;		}		fp = (struct flat_binder_object *)(t->buffer->data + *offp);		switch (fp->type) {		case BINDER_TYPE_BINDER:		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) {					return_error = BR_FAILED_REPLY;					goto err_binder_new_node_failed;				}				node->min_priority = fp->flags & FLAT_BINDER_FLAG_PRIORITY_MASK;				node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);			}			if (fp->cookie != node->cookie) {				binder_user_error("binder: %d:%d sending u%p "					"node %d, cookie mismatch %p != %p\n",					proc->pid, thread->pid,					fp->binder, node->debug_id,					fp->cookie, node->cookie);				goto err_binder_get_ref_for_node_failed;			}			ref = binder_get_ref_for_node(target_proc, node);			if (ref == NULL) {				return_error = BR_FAILED_REPLY;				goto err_binder_get_ref_for_node_failed;			}			if (fp->type == BINDER_TYPE_BINDER)				fp->type = BINDER_TYPE_HANDLE;			else				fp->type = BINDER_TYPE_WEAK_HANDLE;			fp->handle = ref->desc;			binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE, &thread->todo);			if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)				printk(KERN_INFO "        node %d u%p -> ref %d desc %d\n",				       node->debug_id, 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("binder: %d:%d got "					"transaction with invalid "					"handle, %ld\n", proc->pid,					thread->pid, fp->handle);				return_error = BR_FAILED_REPLY;				goto err_binder_get_ref_failed;			}			if (ref->node->proc == target_proc) {				if (fp->type == BINDER_TYPE_HANDLE)					fp->type = BINDER_TYPE_BINDER;				else					fp->type = BINDER_TYPE_WEAK_BINDER;				fp->binder = ref->node->ptr;				fp->cookie = ref->node->cookie;				binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);				if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)					printk(KERN_INFO "        ref %d desc %d -> node %d u%p\n",					       ref->debug_id, ref->desc, ref->node->debug_id, 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;					goto err_binder_get_ref_for_node_failed;				}				fp->handle = new_ref->desc;				binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);				if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)					printk(KERN_INFO "        ref %d desc %d -> ref %d desc %d (node %d)\n",					       ref->debug_id, ref->desc, new_ref->debug_id, new_ref->desc, ref->node->debug_id);			}		} break;		case BINDER_TYPE_FD: {			int target_fd;			struct file *file;			if (reply) {				if (!(in_reply_to->flags & TF_ACCEPT_FDS)) {					binder_user_error("binder: %d:%d got reply with fd, %ld, but target does not allow fds\n",						proc->pid, thread->pid, fp->handle);					return_error = BR_FAILED_REPLY;					goto err_fd_not_allowed;				}			} else if (!target_node->accept_fds) {				binder_user_error("binder: %d:%d got transaction with fd, %ld, but target does not allow fds\n",					proc->pid, thread->pid, fp->handle);				return_error = BR_FAILED_REPLY;				goto err_fd_not_allowed;			}			file = fget(fp->handle);			if (file == NULL) {				binder_user_error("binder: %d:%d got transaction with invalid fd, %ld\n",					proc->pid, thread->pid, fp->handle);				return_error = BR_FAILED_REPLY;				goto err_fget_failed;			}			target_fd = task_get_unused_fd_flags(target_proc->tsk, O_CLOEXEC);			if (target_fd < 0) {				fput(file);				return_error = BR_FAILED_REPLY;				goto err_get_unused_fd_failed;			}			task_fd_install(target_proc->tsk, target_fd, file);			if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)				printk(KERN_INFO "        fd %ld -> %d\n", fp->handle, target_fd);			/* TODO: fput? */			fp->handle = target_fd;		} break;		default:			binder_user_error("binder: %d:%d got transactio"				"n with invalid object type, %lx\n",				proc->pid, thread->pid, fp->type);			return_error = BR_FAILED_REPLY;			goto err_bad_object_type;		}	}	if (reply) {		BUG_ON(t->buffer->async_transaction != 0);		binder_pop_transaction(target_thread, in_reply_to);	} else if (!(t->flags & TF_ONE_WAY)) {		BUG_ON(t->buffer->async_transaction != 0);		t->need_reply = 1;		t->from_parent = thread->transaction_stack;		thread->transaction_stack = t;	} else {		BUG_ON(target_node == NULL);		BUG_ON(t->buffer->async_transaction != 1);		if (target_node->has_async_transaction) {			target_list = &target_node->async_todo;			target_wait = NULL;		} else			target_node->has_async_transaction = 1;	}	t->work.type = BINDER_WORK_TRANSACTION;	list_add_tail(&t->work.entry, target_list);	tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;	list_add_tail(&tcomplete->entry, &thread->todo);	if (target_wait)		wake_up_interruptible(target_wait);	return;err_get_unused_fd_failed:err_fget_failed:err_fd_not_allowed:err_binder_get_ref_for_node_failed:err_binder_get_ref_failed:err_binder_new_node_failed:err_bad_object_type:err_bad_offset:err_copy_data_failed:	binder_transaction_buffer_release(target_proc, t->buffer, offp);	t->buffer->transaction = NULL;	binder_free_buf(target_proc, t->buffer);err_binder_alloc_buf_failed:	kfree(tcomplete);	binder_stats.obj_deleted[BINDER_STAT_TRANSACTION_COMPLETE]++;err_alloc_tcomplete_failed:	kfree(t);	binder_stats.obj_deleted[BINDER_STAT_TRANSACTION]++;err_alloc_t_failed:err_bad_call_stack:err_empty_call_stack:err_dead_binder:err_invalid_target_handle:err_no_context_mgr_node:	if (binder_debug_mask & BINDER_DEBUG_FAILED_TRANSACTION)		printk(KERN_INFO "binder: %d:%d transaction failed %d, size %d-%d\n",			   proc->pid, thread->pid, return_error,			   tr->data_size, tr->offsets_size);	{		struct binder_transaction_log_entry *fe;		fe = binder_transaction_log_add(&binder_transaction_log_failed);		*fe = *e;	}	BUG_ON(thread->return_error != BR_OK);	if (in_reply_to) {		thread->return_error = BR_TRANSACTION_COMPLETE;		binder_send_failed_reply(in_reply_to, return_error);	} else		thread->return_error = return_error;}static voidbinder_transaction_buffer_release(struct binder_proc *proc, struct binder_buffer *buffer, size_t *failed_at){	size_t *offp, *off_end;	int debug_id = buffer->debug_id;	if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)		printk(KERN_INFO "binder: %d buffer release %d, size %d-%d, failed at %p\n",			   proc->pid, buffer->debug_id,			   buffer->data_size, buffer->offsets_size, failed_at);	if (buffer->target_node)		binder_dec_node(buffer->target_node, 1, 0);	offp = (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)) {			printk(KERN_ERR "binder: transaction release %d bad offset %d, size %d\n", debug_id, *offp, buffer->data_size);			continue;		}		fp = (struct flat_binder_object *)(buffer->data + *offp);		switch (fp->type) {		case BINDER_TYPE_BINDER:		case BINDER_TYPE_WEAK_BINDER: {			struct binder_node *node = binder_get_node(proc, fp->binder);			if (node == NULL) {				printk(KERN_ERR "binder: transaction release %d bad node %p\n", debug_id, fp->binder);				break;			}			if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)				printk(KERN_INFO "        node %d u%p\n",				       node->debug_id, 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) {				printk(KERN_ERR "binder: transaction release %d bad handle %ld\n", debug_id, fp->handle);				break;			}			if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)				printk(KERN_INFO "        ref %d desc %d (node %d)\n",				       ref->debug_id, ref->desc, ref->node->debug_id);			binder_dec_ref(ref, fp->type == BINDER_TYPE_HANDLE);		} break;		case BINDER_TYPE_FD:			if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)				printk(KERN_INFO "        fd %ld\n", fp->handle);			if (failed_at)				task_close_fd(proc->tsk, fp->handle);			break;		default:			printk(KERN_ERR "binder: transaction release %d bad object type %lx\n", debug_id, fp->type);			break;		}	}}intbinder_thread_write(struct binder_proc *proc, struct binder_thread *thread,		    void __user *buffer, int size, signed long *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);		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("binder: %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("binder: %d:%d refcou"					"nt 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;			}			if (binder_debug_mask & BINDER_DEBUG_USER_REFS)				printk(KERN_INFO "binder: %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 *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("binder: %d:%d "					"%s u%p no match\n",					proc->pid, thread->pid,					cmd == BC_INCREFS_DONE ?					"BC_INCREFS_DONE" :					"BC_ACQUIRE_DONE",					node_ptr);				break;			}			if (cookie != node->cookie) {				binder_user_error("binder: %d:%d %s u%p node %d"					" cookie mismatch %p != %p\n",					proc->pid, thread->pid,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -