diff options
Diffstat (limited to 'drivers/android/binder.c')
| -rw-r--r-- | drivers/android/binder.c | 63 |
1 files changed, 37 insertions, 26 deletions
diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 535fc881c8da..9e6194224593 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -795,7 +795,7 @@ static struct binder_node *binder_new_node(struct binder_proc *proc, struct flat_binder_object *fp) { struct binder_node *node; - struct binder_node *new_node = kzalloc(sizeof(*node), GFP_KERNEL); + struct binder_node *new_node = kzalloc_obj(*node); if (!new_node) return NULL; @@ -1469,7 +1469,7 @@ static int binder_inc_ref_for_node(struct binder_proc *proc, ref = binder_get_ref_for_node_olocked(proc, node, NULL); if (!ref) { binder_proc_unlock(proc); - new_ref = kzalloc(sizeof(*ref), GFP_KERNEL); + new_ref = kzalloc_obj(*ref); if (!new_ref) return -ENOMEM; binder_proc_lock(proc); @@ -2009,7 +2009,7 @@ static void binder_deferred_fd_close(int fd) { struct binder_task_work_cb *twcb; - twcb = kzalloc(sizeof(*twcb), GFP_KERNEL); + twcb = kzalloc_obj(*twcb); if (!twcb) return; init_task_work(&twcb->twork, binder_do_fd_close); @@ -2386,7 +2386,7 @@ static int binder_translate_fd(u32 fd, binder_size_t fd_offset, * of the fd in the target needs to be done from a * target thread. */ - fixup = kzalloc(sizeof(*fixup), GFP_KERNEL); + fixup = kzalloc_obj(*fixup); if (!fixup) { ret = -ENOMEM; goto err_alloc; @@ -2579,7 +2579,7 @@ static void binder_cleanup_deferred_txn_lists(struct list_head *sgc_head, static int binder_defer_copy(struct list_head *sgc_head, binder_size_t offset, const void __user *sender_uaddr, size_t length) { - struct binder_sg_copy *bc = kzalloc(sizeof(*bc), GFP_KERNEL); + struct binder_sg_copy *bc = kzalloc_obj(*bc); if (!bc) return -ENOMEM; @@ -2622,7 +2622,7 @@ static int binder_defer_copy(struct list_head *sgc_head, binder_size_t offset, static int binder_add_fixup(struct list_head *pf_head, binder_size_t offset, binder_uintptr_t fixup, size_t skip_size) { - struct binder_ptr_fixup *pf = kzalloc(sizeof(*pf), GFP_KERNEL); + struct binder_ptr_fixup *pf = kzalloc_obj(*pf); struct binder_ptr_fixup *tmppf; if (!pf) @@ -2991,6 +2991,10 @@ static void binder_set_txn_from_error(struct binder_transaction *t, int id, * @t: the binder transaction that failed * @data_size: the user provided data size for the transaction * @error: enum binder_driver_return_protocol returned to sender + * + * Note that t->buffer is not safe to access here, as it may have been + * released (or not yet allocated). Callers should guarantee all the + * transaction items used here are safe to access. */ static void binder_netlink_report(struct binder_proc *proc, struct binder_transaction *t, @@ -3097,7 +3101,7 @@ static void binder_transaction(struct binder_proc *proc, binder_set_extended_error(&thread->ee, t_debug_id, BR_OK, 0); binder_inner_proc_unlock(proc); - t = kzalloc(sizeof(*t), GFP_KERNEL); + t = kzalloc_obj(*t); if (!t) { binder_txn_error("%d:%d cannot allocate transaction\n", thread->pid, proc->pid); @@ -3113,7 +3117,7 @@ static void binder_transaction(struct binder_proc *proc, t->start_time = t_start_time; t->from_pid = proc->pid; t->from_tid = thread->pid; - t->sender_euid = task_euid(proc->tsk); + t->sender_euid = current_euid(); t->code = tr->code; t->flags = tr->flags; t->priority = task_nice(current); @@ -3316,7 +3320,7 @@ static void binder_transaction(struct binder_proc *proc, e->to_thread = target_thread->pid; e->to_proc = target_proc->pid; - tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL); + tcomplete = kzalloc_obj(*tcomplete); if (tcomplete == NULL) { binder_txn_error("%d:%d cannot allocate work for transaction\n", thread->pid, proc->pid); @@ -3780,6 +3784,14 @@ static void binder_transaction(struct binder_proc *proc, goto err_dead_proc_or_thread; } } else { + /* + * Make a transaction copy. It is not safe to access 't' after + * binder_proc_transaction() reported a pending frozen. The + * target could thaw and consume the transaction at any point. + * Instead, use a safe 't_copy' for binder_netlink_report(). + */ + struct binder_transaction t_copy = *t; + BUG_ON(target_node == NULL); BUG_ON(t->buffer->async_transaction != 1); return_error = binder_proc_transaction(t, target_proc, NULL); @@ -3790,7 +3802,7 @@ static void binder_transaction(struct binder_proc *proc, */ if (return_error == BR_TRANSACTION_PENDING_FROZEN) { tcomplete->type = BINDER_WORK_TRANSACTION_PENDING; - binder_netlink_report(proc, t, tr->data_size, + binder_netlink_report(proc, &t_copy, tr->data_size, return_error); } binder_enqueue_thread_work(thread, tcomplete); @@ -3812,8 +3824,9 @@ static void binder_transaction(struct binder_proc *proc, return; err_dead_proc_or_thread: - binder_txn_error("%d:%d dead process or thread\n", - thread->pid, proc->pid); + binder_txn_error("%d:%d %s process or thread\n", + proc->pid, thread->pid, + return_error == BR_FROZEN_REPLY ? "frozen" : "dead"); return_error_line = __LINE__; binder_dequeue_work(proc, tcomplete); err_translate_failed: @@ -3913,7 +3926,7 @@ binder_request_freeze_notification(struct binder_proc *proc, struct binder_ref_freeze *freeze; struct binder_ref *ref; - freeze = kzalloc(sizeof(*freeze), GFP_KERNEL); + freeze = kzalloc_obj(*freeze); if (!freeze) return -ENOMEM; binder_proc_lock(proc); @@ -4381,7 +4394,7 @@ static int binder_thread_write(struct binder_proc *proc, * Allocate memory for death notification * before taking lock */ - death = kzalloc(sizeof(*death), GFP_KERNEL); + death = kzalloc_obj(*death); if (death == NULL) { WARN_ON(thread->return_error.cmd != BR_OK); @@ -4510,7 +4523,7 @@ static int binder_thread_write(struct binder_proc *proc, } } binder_debug(BINDER_DEBUG_DEAD_BINDER, - "%d:%d BC_DEAD_BINDER_DONE %016llx found %pK\n", + "%d:%d BC_DEAD_BINDER_DONE %016llx found %p\n", proc->pid, thread->pid, (u64)cookie, death); if (death == NULL) { @@ -5280,7 +5293,7 @@ static struct binder_thread *binder_get_thread(struct binder_proc *proc) thread = binder_get_thread_ilocked(proc, NULL); binder_inner_proc_unlock(proc); if (!thread) { - new_thread = kzalloc(sizeof(*thread), GFP_KERNEL); + new_thread = kzalloc_obj(*thread); if (new_thread == NULL) return NULL; binder_inner_proc_lock(proc); @@ -5889,9 +5902,8 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) goto err; } - target_procs = kcalloc(target_procs_count, - sizeof(struct binder_proc *), - GFP_KERNEL); + target_procs = kzalloc_objs(struct binder_proc *, + target_procs_count); if (!target_procs) { mutex_unlock(&binder_procs_lock); @@ -6015,7 +6027,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) { struct binder_proc *proc = filp->private_data; - if (proc->tsk != current->group_leader) + if (!same_thread_group(proc->tsk, current)) return -EINVAL; binder_debug(BINDER_DEBUG_OPEN_CLOSE, @@ -6046,17 +6058,17 @@ static int binder_open(struct inode *nodp, struct file *filp) bool existing_pid = false; binder_debug(BINDER_DEBUG_OPEN_CLOSE, "%s: %d:%d\n", __func__, - current->group_leader->pid, current->pid); + current->tgid, current->pid); - proc = kzalloc(sizeof(*proc), GFP_KERNEL); + proc = kzalloc_obj(*proc); if (proc == NULL) return -ENOMEM; dbitmap_init(&proc->dmap); spin_lock_init(&proc->inner_lock); spin_lock_init(&proc->outer_lock); - get_task_struct(current->group_leader); - proc->tsk = current->group_leader; + proc->tsk = get_task_struct(current->group_leader); + proc->pid = current->tgid; proc->cred = get_cred(filp->f_cred); INIT_LIST_HEAD(&proc->todo); init_waitqueue_head(&proc->freeze_wait); @@ -6075,7 +6087,6 @@ static int binder_open(struct inode *nodp, struct file *filp) binder_alloc_init(&proc->alloc); binder_stats_created(BINDER_STAT_PROC); - proc->pid = current->group_leader->pid; INIT_LIST_HEAD(&proc->delivered_death); INIT_LIST_HEAD(&proc->delivered_freeze); INIT_LIST_HEAD(&proc->waiting_threads); @@ -7053,7 +7064,7 @@ static int __init init_binder_device(const char *name) int ret; struct binder_device *binder_device; - binder_device = kzalloc(sizeof(*binder_device), GFP_KERNEL); + binder_device = kzalloc_obj(*binder_device); if (!binder_device) return -ENOMEM; |
