3703 lines · 101.5 KB · C
RawDownload
/* binder.c * * Android IPC Subsystem * * Copyright (C) 2007-2008 Google, Inc. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <asm/cacheflush.h>#include <linux/fdtable.h>#include <linux/file.h>#include <linux/freezer.h>#include <linux/fs.h>#include <linux/list.h>#include <linux/miscdevice.h>#include <linux/mm.h>#include <linux/module.h>#include <linux/mutex.h>#include <linux/nsproxy.h>#include <linux/poll.h>#include <linux/debugfs.h>#include <linux/rbtree.h>#include <linux/sched.h>#include <linux/seq_file.h>#include <linux/uaccess.h>#include <linux/vmalloc.h>#include <linux/slab.h>#include <linux/pid_namespace.h>#include <linux/security.h> #ifdef CONFIG_ANDROID_BINDER_IPC_32BIT#define BINDER_IPC_32BIT 1#endif #include <uapi/linux/android/binder.h>#include "binder_trace.h" static DEFINE_MUTEX(binder_main_lock);static DEFINE_MUTEX(binder_deferred_lock);static DEFINE_MUTEX(binder_mmap_lock); static HLIST_HEAD(binder_procs);static HLIST_HEAD(binder_deferred_list);static HLIST_HEAD(binder_dead_nodes); static struct dentry *binder_debugfs_dir_entry_root;static struct dentry *binder_debugfs_dir_entry_proc;static struct binder_node *binder_context_mgr_node;static kuid_t binder_context_mgr_uid = INVALID_UID;static int binder_last_id;static struct workqueue_struct *binder_deferred_workqueue; #define BINDER_DEBUG_ENTRY(name) \static int binder_##name##_open(struct inode *inode, struct file *file) \{ \	return single_open(file, binder_##name##_show, inode->i_private); \} \\static const struct file_operations binder_##name##_fops = { \	.owner = THIS_MODULE, \	.open = binder_##name##_open, \	.read = seq_read, \	.llseek = seq_lseek, \	.release = single_release, \} static int binder_proc_show(struct seq_file *m, void *unused);BINDER_DEBUG_ENTRY(proc); /* This is only defined in include/asm-arm/sizes.h */#ifndef SZ_1K#define SZ_1K                               0x400#endif #ifndef SZ_4M#define SZ_4M                               0x400000#endif #define FORBIDDEN_MMAP_FLAGS                (VM_WRITE) #define BINDER_SMALL_BUF_SIZE (PAGE_SIZE * 64) enum {	BINDER_DEBUG_USER_ERROR             = 1U << 0,	BINDER_DEBUG_FAILED_TRANSACTION     = 1U << 1,	BINDER_DEBUG_DEAD_TRANSACTION       = 1U << 2,	BINDER_DEBUG_OPEN_CLOSE             = 1U << 3,	BINDER_DEBUG_DEAD_BINDER            = 1U << 4,	BINDER_DEBUG_DEATH_NOTIFICATION     = 1U << 5,	BINDER_DEBUG_READ_WRITE             = 1U << 6,	BINDER_DEBUG_USER_REFS              = 1U << 7,	BINDER_DEBUG_THREADS                = 1U << 8,	BINDER_DEBUG_TRANSACTION            = 1U << 9,	BINDER_DEBUG_TRANSACTION_COMPLETE   = 1U << 10,	BINDER_DEBUG_FREE_BUFFER            = 1U << 11,	BINDER_DEBUG_INTERNAL_REFS          = 1U << 12,	BINDER_DEBUG_BUFFER_ALLOC           = 1U << 13,	BINDER_DEBUG_PRIORITY_CAP           = 1U << 14,	BINDER_DEBUG_BUFFER_ALLOC_ASYNC     = 1U << 15,};static uint32_t binder_debug_mask = BINDER_DEBUG_USER_ERROR |	BINDER_DEBUG_FAILED_TRANSACTION | BINDER_DEBUG_DEAD_TRANSACTION;module_param_named(debug_mask, binder_debug_mask, uint, S_IWUSR | S_IRUGO); static bool binder_debug_no_lock;module_param_named(proc_no_lock, binder_debug_no_lock, bool, S_IWUSR | S_IRUGO); static DECLARE_WAIT_QUEUE_HEAD(binder_user_error_wait);static int binder_stop_on_user_error; 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);	return ret;}module_param_call(stop_on_user_error, binder_set_stop_on_user_error,	param_get_int, &binder_stop_on_user_error, S_IWUSR | S_IRUGO); #define binder_debug(mask, x...) \	do { \		if (binder_debug_mask & mask) \			pr_info(x); \	} while (0) #define binder_user_error(x...) \	do { \		if (binder_debug_mask & BINDER_DEBUG_USER_ERROR) \			pr_info(x); \		if (binder_stop_on_user_error) \			binder_stop_on_user_error = 2; \	} while (0) enum binder_stat_types {	BINDER_STAT_PROC,	BINDER_STAT_THREAD,	BINDER_STAT_NODE,	BINDER_STAT_REF,	BINDER_STAT_DEATH,	BINDER_STAT_TRANSACTION,	BINDER_STAT_TRANSACTION_COMPLETE,	BINDER_STAT_COUNT}; struct binder_stats {	int br[_IOC_NR(BR_FAILED_REPLY) + 1];	int bc[_IOC_NR(BC_DEAD_BINDER_DONE) + 1];	int obj_created[BINDER_STAT_COUNT];	int obj_deleted[BINDER_STAT_COUNT];}; static struct binder_stats binder_stats; static inline void binder_stats_deleted(enum binder_stat_types type){	binder_stats.obj_deleted[type]++;} static inline void binder_stats_created(enum binder_stat_types type){	binder_stats.obj_created[type]++;} struct binder_transaction_log_entry {	int debug_id;	int call_type;	int from_proc;	int from_thread;	int target_handle;	int to_proc;	int to_thread;	int to_node;	int data_size;	int offsets_size;};struct binder_transaction_log {	int next;	int full;	struct binder_transaction_log_entry entry[32];};static struct binder_transaction_log binder_transaction_log;static struct binder_transaction_log binder_transaction_log_failed; 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++;	if (log->next == ARRAY_SIZE(log->entry)) {		log->next = 0;		log->full = 1;	}	return e;} struct binder_work {	struct list_head entry;	enum {		BINDER_WORK_TRANSACTION = 1,		BINDER_WORK_TRANSACTION_COMPLETE,		BINDER_WORK_NODE,		BINDER_WORK_DEAD_BINDER,		BINDER_WORK_DEAD_BINDER_AND_CLEAR,		BINDER_WORK_CLEAR_DEATH_NOTIFICATION,	} type;}; struct binder_node {	int debug_id;	struct binder_work work;	union {		struct rb_node rb_node;		struct hlist_node dead_node;	};	struct binder_proc *proc;	struct hlist_head refs;	int internal_strong_refs;	int local_weak_refs;	int local_strong_refs;	binder_uintptr_t ptr;	binder_uintptr_t cookie;	unsigned has_strong_ref:1;	unsigned pending_strong_ref:1;	unsigned has_weak_ref:1;	unsigned pending_weak_ref:1;	unsigned has_async_transaction:1;	unsigned accept_fds:1;	unsigned min_priority:8;	struct list_head async_todo;}; struct binder_ref_death {	struct binder_work work;	binder_uintptr_t cookie;}; struct binder_ref {	/* Lookups needed: */	/*   node + proc => ref (transaction) */	/*   desc + proc => ref (transaction, inc/dec ref) */	/*   node => refs + procs (proc exit) */	int debug_id;	struct rb_node rb_node_desc;	struct rb_node rb_node_node;	struct hlist_node node_entry;	struct binder_proc *proc;	struct binder_node *node;	uint32_t desc;	int strong;	int weak;	struct binder_ref_death *death;}; struct binder_buffer {	struct list_head entry; /* free and allocated entries by address */	struct rb_node rb_node; /* free entry by size or allocated entry */				/* by address */	unsigned free:1;	unsigned allow_user_free:1;	unsigned async_transaction:1;	unsigned debug_id:29; 	struct binder_transaction *transaction; 	struct binder_node *target_node;	size_t data_size;	size_t offsets_size;	uint8_t data[0];}; enum binder_deferred_state {	BINDER_DEFERRED_PUT_FILES    = 0x01,	BINDER_DEFERRED_FLUSH        = 0x02,	BINDER_DEFERRED_RELEASE      = 0x04,}; struct binder_proc {	struct hlist_node proc_node;	struct rb_root threads;	struct rb_root nodes;	struct rb_root refs_by_desc;	struct rb_root refs_by_node;	int pid;	struct vm_area_struct *vma;	struct mm_struct *vma_vm_mm;	struct task_struct *tsk;	struct files_struct *files;	struct hlist_node deferred_work_node;	int deferred_work;	void *buffer;	ptrdiff_t user_buffer_offset; 	struct list_head buffers;	struct rb_root free_buffers;	struct rb_root allocated_buffers;	size_t free_async_space; 	struct page **pages;	size_t buffer_size;	uint32_t buffer_free;	struct list_head todo;	wait_queue_head_t wait;	struct binder_stats stats;	struct list_head delivered_death;	int max_threads;	int requested_threads;	int requested_threads_started;	int ready_threads;	long default_priority;	struct dentry *debugfs_entry;}; enum {	BINDER_LOOPER_STATE_REGISTERED  = 0x01,	BINDER_LOOPER_STATE_ENTERED     = 0x02,	BINDER_LOOPER_STATE_EXITED      = 0x04,	BINDER_LOOPER_STATE_INVALID     = 0x08,	BINDER_LOOPER_STATE_WAITING     = 0x10,	BINDER_LOOPER_STATE_NEED_RETURN = 0x20}; struct binder_thread {	struct binder_proc *proc;	struct rb_node rb_node;	int pid;	int looper;	struct binder_transaction *transaction_stack;	struct list_head todo;	uint32_t return_error; /* Write failed, return error code in read buf */	uint32_t return_error2; /* Write failed, return error code in read */		/* buffer. Used when sending a reply to a dead process that */		/* we are also waiting on */	wait_queue_head_t wait;	struct binder_stats stats;}; struct binder_transaction {	int debug_id;	struct binder_work work;	struct binder_thread *from;	struct binder_transaction *from_parent;	struct binder_proc *to_proc;	struct binder_thread *to_thread;	struct binder_transaction *to_parent;	unsigned need_reply:1;	/* unsigned is_dead:1; */	/* not used at the moment */ 	struct binder_buffer *buffer;	unsigned int	code;	unsigned int	flags;	long	priority;	long	saved_priority;	kuid_t	sender_euid;}; static voidbinder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer); static int task_get_unused_fd_flags(struct binder_proc *proc, int flags){	struct files_struct *files = proc->files;	unsigned long rlim_cur;	unsigned long irqs; 	if (files == NULL)		return -ESRCH; 	if (!lock_task_sighand(proc->tsk, &irqs))		return -EMFILE; 	rlim_cur = task_rlimit(proc->tsk, RLIMIT_NOFILE);	unlock_task_sighand(proc->tsk, &irqs); 	return __alloc_fd(files, 0, rlim_cur, flags);} /* * copied from fd_install */static void task_fd_install(	struct binder_proc *proc, unsigned int fd, struct file *file){	if (proc->files)		__fd_install(proc->files, fd, file);} /* * copied from sys_close */static long task_close_fd(struct binder_proc *proc, unsigned int fd){	int retval; 	if (proc->files == NULL)		return -ESRCH; 	retval = __close_fd(proc->files, fd);	/* can't restart close syscall because file table entry was cleared */	if (unlikely(retval == -ERESTARTSYS ||		     retval == -ERESTARTNOINTR ||		     retval == -ERESTARTNOHAND ||		     retval == -ERESTART_RESTARTBLOCK))		retval = -EINTR; 	return retval;} static inline void binder_lock(const char *tag){	trace_binder_lock(tag);	mutex_lock(&binder_main_lock);	trace_binder_locked(tag);} static inline void binder_unlock(const char *tag){	trace_binder_unlock(tag);	mutex_unlock(&binder_main_lock);} static void binder_set_nice(long nice){	long min_nice; 	if (can_nice(current, nice)) {		set_user_nice(current, nice);		return;	}	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 <= MAX_NICE)		return;	binder_user_error("%d RLIMIT_NICE not set\n", current->pid);} static size_t binder_buffer_size(struct binder_proc *proc,				 struct binder_buffer *buffer){	if (list_is_last(&buffer->entry, &proc->buffers))		return proc->buffer + proc->buffer_size - (void *)buffer->data;	return (size_t)list_entry(buffer->entry.next,			  struct binder_buffer, entry) - (size_t)buffer->data;} static void binder_insert_free_buffer(struct binder_proc *proc,				      struct binder_buffer *new_buffer){	struct rb_node **p = &proc->free_buffers.rb_node;	struct rb_node *parent = NULL;	struct binder_buffer *buffer;	size_t buffer_size;	size_t new_buffer_size; 	BUG_ON(!new_buffer->free); 	new_buffer_size = binder_buffer_size(proc, new_buffer); 	binder_debug(BINDER_DEBUG_BUFFER_ALLOC,		     "%d: add free buffer, size %zd, at %p\n",		      proc->pid, new_buffer_size, new_buffer); 	while (*p) {		parent = *p;		buffer = rb_entry(parent, struct binder_buffer, rb_node);		BUG_ON(!buffer->free); 		buffer_size = binder_buffer_size(proc, buffer); 		if (new_buffer_size < buffer_size)			p = &parent->rb_left;		else			p = &parent->rb_right;	}	rb_link_node(&new_buffer->rb_node, parent, p);	rb_insert_color(&new_buffer->rb_node, &proc->free_buffers);} static void binder_insert_allocated_buffer(struct binder_proc *proc,					   struct binder_buffer *new_buffer)

Lines 1–500 of 3703.