aboutsummaryrefslogtreecommitdiff
path: root/drivers/android/binder.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/android/binder.c')
-rw-r--r--drivers/android/binder.c63
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;