3611 lines · 99.9 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. * */ #include <asm/cacheflush.h>#include <linux/fdtable.h>#include <linux/file.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 "binder.h" static DEFINE_MUTEX(binder_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 uid_t binder_context_mgr_uid = -1;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) \			printk(KERN_INFO x); \	} while (0) #define binder_user_error(x...) \	do { \		if (binder_debug_mask & BINDER_DEBUG_USER_ERROR) \			printk(KERN_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;	void __user *ptr;	void __user *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;	void __user *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;	uid_t	sender_euid;}; static voidbinder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer); /* * copied from get_unused_fd_flags */int task_get_unused_fd_flags(struct binder_proc *proc, int flags){	struct files_struct *files = proc->files;	int fd, error;	struct fdtable *fdt;	unsigned long rlim_cur;	unsigned long irqs; 	if (files == NULL)		return -ESRCH; 	error = -EMFILE;	spin_lock(&files->file_lock); repeat:	fdt = files_fdtable(files);	fd = find_next_zero_bit(fdt->open_fds, fdt->max_fds, files->next_fd); 	/*	 * N.B. For clone tasks sharing a files structure, this test	 * will limit the total number of files that can be opened.	 */	rlim_cur = 0;	if (lock_task_sighand(proc->tsk, &irqs)) {		rlim_cur = proc->tsk->signal->rlim[RLIMIT_NOFILE].rlim_cur;		unlock_task_sighand(proc->tsk, &irqs);	}	if (fd >= rlim_cur)		goto out; 	/* Do we need to expand the fd array or fd set?  */	error = expand_files(files, fd);	if (error < 0)		goto out; 	if (error) {		/*		 * If we needed to expand the fs array we		 * might have blocked - try again.		 */		error = -EMFILE;		goto repeat;	} 	__set_open_fd(fd, fdt);	if (flags & O_CLOEXEC)		__set_close_on_exec(fd, fdt);	else		__clear_close_on_exec(fd, fdt);	files->next_fd = fd + 1;#if 1	/* Sanity check */	if (fdt->fd[fd] != NULL) {		printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd);		fdt->fd[fd] = NULL;	}#endif	error = fd; out:	spin_unlock(&files->file_lock);	return error;} /* * copied from fd_install */static void task_fd_install(	struct binder_proc *proc, unsigned int fd, struct file *file){	struct files_struct *files = proc->files;	struct fdtable *fdt; 	if (files == NULL)		return; 	spin_lock(&files->file_lock);	fdt = files_fdtable(files);	BUG_ON(fdt->fd[fd] != NULL);	rcu_assign_pointer(fdt->fd[fd], file);	spin_unlock(&files->file_lock);} /* * copied from __put_unused_fd in open.c */static void __put_unused_fd(struct files_struct *files, unsigned int fd){	struct fdtable *fdt = files_fdtable(files);	__clear_open_fd(fd, fdt);	if (fd < files->next_fd)		files->next_fd = fd;} /* * copied from sys_close */static long task_close_fd(struct binder_proc *proc, unsigned int fd){	struct file *filp;	struct files_struct *files = proc->files;	struct fdtable *fdt;	int retval; 	if (files == NULL)		return -ESRCH; 	spin_lock(&files->file_lock);	fdt = files_fdtable(files);	if (fd >= fdt->max_fds)		goto out_unlock;	filp = fdt->fd[fd];	if (!filp)		goto out_unlock;	rcu_assign_pointer(fdt->fd[fd], NULL);	__clear_close_on_exec(fd, fdt);	__put_unused_fd(files, fd);	spin_unlock(&files->file_lock);	retval = filp_close(filp, files); 	/* 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; out_unlock:	spin_unlock(&files->file_lock);	return -EBADF;}

Lines 1–500 of 3611.