Staging: android: binder: Don't call dump_stack in binder_vma_open
Staging: android: binder: Fix crashes when sharing a binder file between processes drivers:staging:android Typos: fix some comments that have typos in them. fs: Remove missed ->fds_bits from cessation use of fd_set structs internally Staging:android: Change type for binder_debug_no_lock switch to bool Staging: android: binder: Fix use-after-free bug
This commit is contained in:
parent
e20f7d7077
commit
9b8229cafb
270
drivers/staging/android/binder.c
Normal file → Executable file
270
drivers/staging/android/binder.c
Normal file → Executable file
@ -3,7 +3,6 @@
|
||||
* Android IPC Subsystem
|
||||
*
|
||||
* Copyright (C) 2007-2008 Google, Inc.
|
||||
* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
@ -31,14 +30,15 @@
|
||||
#include <linux/rbtree.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/slab.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);
|
||||
@ -98,12 +98,12 @@ enum {
|
||||
BINDER_DEBUG_BUFFER_ALLOC = 1U << 13,
|
||||
BINDER_DEBUG_PRIORITY_CAP = 1U << 14,
|
||||
BINDER_DEBUG_BUFFER_ALLOC_ASYNC = 1U << 15,
|
||||
BINDER_DEBUG_TOP_ERRORS = 1U << 16,
|
||||
BINDER_DEBUG_TOP_ERRORS = 1U << 16,
|
||||
};
|
||||
static uint32_t binder_debug_mask;
|
||||
module_param_named(debug_mask, binder_debug_mask, uint, S_IWUSR | S_IRUGO);
|
||||
|
||||
static int binder_debug_no_lock;
|
||||
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);
|
||||
@ -258,7 +258,7 @@ struct binder_ref {
|
||||
};
|
||||
|
||||
struct binder_buffer {
|
||||
struct list_head entry; /* free and allocated entries by addesss */
|
||||
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;
|
||||
@ -288,6 +288,7 @@ struct binder_proc {
|
||||
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;
|
||||
@ -380,8 +381,7 @@ int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
|
||||
|
||||
repeat:
|
||||
fdt = files_fdtable(files);
|
||||
fd = find_next_zero_bit(fdt->open_fds->fds_bits, fdt->max_fds,
|
||||
files->next_fd);
|
||||
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
|
||||
@ -633,6 +633,11 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
|
||||
if (mm) {
|
||||
down_write(&mm->mmap_sem);
|
||||
vma = proc->vma;
|
||||
if (vma && mm != proc->vma_vm_mm) {
|
||||
pr_err("binder: %d: vma mm and task mm mismatch\n",
|
||||
proc->pid);
|
||||
vma = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (allocate == 0)
|
||||
@ -640,8 +645,8 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
|
||||
|
||||
if (vma == NULL) {
|
||||
binder_debug(BINDER_DEBUG_TOP_ERRORS,
|
||||
"binder: %d: binder_alloc_buf failed to "
|
||||
"map pages in userspace, no vma\n", proc->pid);
|
||||
"binder: %d: binder_alloc_buf failed to "
|
||||
"map pages in userspace, no vma\n", proc->pid);
|
||||
goto err_no_vma;
|
||||
}
|
||||
|
||||
@ -654,8 +659,8 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
|
||||
*page = alloc_page(GFP_KERNEL | __GFP_ZERO);
|
||||
if (*page == NULL) {
|
||||
binder_debug(BINDER_DEBUG_TOP_ERRORS,
|
||||
"binder: %d: binder_alloc_buf failed "
|
||||
"for page at %p\n", proc->pid, page_addr);
|
||||
"binder: %d: binder_alloc_buf failed "
|
||||
"for page at %p\n", proc->pid, page_addr);
|
||||
goto err_alloc_page_failed;
|
||||
}
|
||||
tmp_area.addr = page_addr;
|
||||
@ -664,9 +669,9 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
|
||||
ret = map_vm_area(&tmp_area, PAGE_KERNEL, &page_array_ptr);
|
||||
if (ret) {
|
||||
binder_debug(BINDER_DEBUG_TOP_ERRORS,
|
||||
"binder: %d: binder_alloc_buf failed "
|
||||
"to map page at %p in kernel\n",
|
||||
proc->pid, page_addr);
|
||||
"binder: %d: binder_alloc_buf failed "
|
||||
"to map page at %p in kernel\n",
|
||||
proc->pid, page_addr);
|
||||
goto err_map_kernel_failed;
|
||||
}
|
||||
user_page_addr =
|
||||
@ -674,9 +679,9 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
|
||||
ret = vm_insert_page(vma, user_page_addr, page[0]);
|
||||
if (ret) {
|
||||
binder_debug(BINDER_DEBUG_TOP_ERRORS,
|
||||
"binder: %d: binder_alloc_buf failed "
|
||||
"to map page at %lx in userspace\n",
|
||||
proc->pid, user_page_addr);
|
||||
"binder: %d: binder_alloc_buf failed "
|
||||
"to map page at %lx in userspace\n",
|
||||
proc->pid, user_page_addr);
|
||||
goto err_vm_insert_page_failed;
|
||||
}
|
||||
/* vm_insert_page does not seem to increment the refcount */
|
||||
@ -724,8 +729,8 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,
|
||||
|
||||
if (proc->vma == NULL) {
|
||||
binder_debug(BINDER_DEBUG_TOP_ERRORS,
|
||||
"binder: %d: binder_alloc_buf, no vma\n",
|
||||
proc->pid);
|
||||
"binder: %d: binder_alloc_buf, no vma\n",
|
||||
proc->pid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -763,8 +768,8 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,
|
||||
}
|
||||
if (best_fit == NULL) {
|
||||
binder_debug(BINDER_DEBUG_TOP_ERRORS,
|
||||
"binder: %d: binder_alloc_buf size %zd failed, "
|
||||
"no address space\n", proc->pid, size);
|
||||
"binder: %d: binder_alloc_buf size %zd failed, "
|
||||
"no address space\n", proc->pid, size);
|
||||
return NULL;
|
||||
}
|
||||
if (n == NULL) {
|
||||
@ -999,8 +1004,8 @@ static int binder_inc_node(struct binder_node *node, int strong, int internal,
|
||||
!(node == binder_context_mgr_node &&
|
||||
node->has_strong_ref)) {
|
||||
binder_debug(BINDER_DEBUG_TOP_ERRORS,
|
||||
"binder: invalid inc strong "
|
||||
"node for %d\n", node->debug_id);
|
||||
"binder: invalid inc strong "
|
||||
"node for %d\n", node->debug_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
node->internal_strong_refs++;
|
||||
@ -1016,8 +1021,8 @@ static int binder_inc_node(struct binder_node *node, int strong, int internal,
|
||||
if (!node->has_weak_ref && list_empty(&node->work.entry)) {
|
||||
if (target_list == NULL) {
|
||||
binder_debug(BINDER_DEBUG_TOP_ERRORS,
|
||||
"binder: invalid inc weak node "
|
||||
"for %d\n", node->debug_id);
|
||||
"binder: invalid inc weak node "
|
||||
"for %d\n", node->debug_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
list_add_tail(&node->work.entry, target_list);
|
||||
@ -1053,7 +1058,7 @@ static int binder_dec_node(struct binder_node *node, int strong, int internal)
|
||||
if (node->proc) {
|
||||
rb_erase(&node->rb_node, &node->proc->nodes);
|
||||
binder_debug(BINDER_DEBUG_INTERNAL_REFS,
|
||||
"binder: refless node %d deleted\n",
|
||||
"binder: refless node %d deleted\n",
|
||||
node->debug_id);
|
||||
} else {
|
||||
hlist_del(&node->dead_node);
|
||||
@ -1272,8 +1277,7 @@ static void binder_send_failed_reply(struct binder_transaction *t,
|
||||
binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
|
||||
"binder: send failed reply for "
|
||||
"transaction %d to %d:%d\n",
|
||||
t->debug_id,
|
||||
target_thread->proc->pid,
|
||||
t->debug_id, target_thread->proc->pid,
|
||||
target_thread->pid);
|
||||
|
||||
binder_pop_transaction(target_thread, t);
|
||||
@ -1281,11 +1285,12 @@ static void binder_send_failed_reply(struct binder_transaction *t,
|
||||
wake_up_interruptible(&target_thread->wait);
|
||||
} else {
|
||||
binder_debug(BINDER_DEBUG_TOP_ERRORS,
|
||||
"binder: reply failed, target "
|
||||
"thread, %d:%d, has error code %d "
|
||||
"already\n", target_thread->proc->pid,
|
||||
target_thread->pid,
|
||||
target_thread->return_error);
|
||||
"binder: reply failed, target "
|
||||
"thread, %d:%d, has error code %d "
|
||||
"already\n",
|
||||
target_thread->proc->pid,
|
||||
target_thread->pid,
|
||||
target_thread->return_error);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
@ -1319,15 +1324,14 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
|
||||
int debug_id = buffer->debug_id;
|
||||
|
||||
binder_debug(BINDER_DEBUG_TRANSACTION,
|
||||
"binder: %d buffer release %d, size %zd-%zd, failed at"
|
||||
" %p\n", proc->pid, buffer->debug_id,
|
||||
"binder: %d buffer release %d, size %zd-%zd, 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 *)));
|
||||
offp = (size_t *)(buffer->data + ALIGN(buffer->data_size, sizeof(void *)));
|
||||
if (failed_at)
|
||||
off_end = failed_at;
|
||||
else
|
||||
@ -1338,44 +1342,41 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
|
||||
buffer->data_size < sizeof(*fp) ||
|
||||
!IS_ALIGNED(*offp, sizeof(void *))) {
|
||||
binder_debug(BINDER_DEBUG_TOP_ERRORS,
|
||||
"binder: transaction release %d bad"
|
||||
"offset %zd, size %zd\n", debug_id,
|
||||
*offp, buffer->data_size);
|
||||
"binder: transaction release %d bad"
|
||||
"offset %zd, size %zd\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);
|
||||
struct binder_node *node = binder_get_node(proc, fp->binder);
|
||||
if (node == NULL) {
|
||||
binder_debug(BINDER_DEBUG_TOP_ERRORS,
|
||||
"binder: transaction release %d"
|
||||
" bad node %p\n", debug_id, fp->binder);
|
||||
"binder: transaction release %d"
|
||||
" bad node %p\n", debug_id,
|
||||
fp->binder);
|
||||
break;
|
||||
}
|
||||
binder_debug(BINDER_DEBUG_TRANSACTION,
|
||||
" node %d u%p\n",
|
||||
node->debug_id, node->ptr);
|
||||
binder_dec_node(node, fp->type == BINDER_TYPE_BINDER,
|
||||
0);
|
||||
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);
|
||||
struct binder_ref *ref = binder_get_ref(proc, fp->handle);
|
||||
if (ref == NULL) {
|
||||
binder_debug(BINDER_DEBUG_TOP_ERRORS,
|
||||
"binder: transaction release %d"
|
||||
" bad handle %ld\n", debug_id,
|
||||
fp->handle);
|
||||
"binder: transaction release %d"
|
||||
" bad handle %ld\n", debug_id,
|
||||
fp->handle);
|
||||
break;
|
||||
}
|
||||
binder_debug(BINDER_DEBUG_TRANSACTION,
|
||||
" ref %d desc %d (node %d)\n",
|
||||
ref->debug_id, ref->desc,
|
||||
ref->node->debug_id);
|
||||
ref->debug_id, ref->desc, ref->node->debug_id);
|
||||
binder_dec_ref(ref, fp->type == BINDER_TYPE_HANDLE);
|
||||
} break;
|
||||
|
||||
@ -1388,8 +1389,8 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
|
||||
|
||||
default:
|
||||
binder_debug(BINDER_DEBUG_TOP_ERRORS,
|
||||
"binder: transaction release %d bad "
|
||||
"object type %lx\n", debug_id, fp->type);
|
||||
"binder: transaction release %d bad "
|
||||
"object type %lx\n", debug_id, fp->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1614,19 +1615,15 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
case BINDER_TYPE_BINDER:
|
||||
case BINDER_TYPE_WEAK_BINDER: {
|
||||
struct binder_ref *ref;
|
||||
struct binder_node *node = binder_get_node(proc,
|
||||
fp->binder);
|
||||
struct binder_node *node = binder_get_node(proc, fp->binder);
|
||||
if (node == NULL) {
|
||||
node = binder_new_node(proc, fp->binder,
|
||||
fp->cookie);
|
||||
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);
|
||||
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 "
|
||||
@ -1656,8 +1653,7 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
} break;
|
||||
case BINDER_TYPE_HANDLE:
|
||||
case BINDER_TYPE_WEAK_HANDLE: {
|
||||
struct binder_ref *ref = binder_get_ref(proc,
|
||||
fp->handle);
|
||||
struct binder_ref *ref = binder_get_ref(proc, fp->handle);
|
||||
if (ref == NULL) {
|
||||
binder_user_error("binder: %d:%d got "
|
||||
"transaction with invalid "
|
||||
@ -1673,31 +1669,24 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
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);
|
||||
binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);
|
||||
binder_debug(BINDER_DEBUG_TRANSACTION,
|
||||
" ref %d desc %d -> node %d u%p\n",
|
||||
ref->debug_id, ref->desc,
|
||||
ref->node->debug_id,
|
||||
ref->node->ptr);
|
||||
" 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);
|
||||
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);
|
||||
binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);
|
||||
binder_debug(BINDER_DEBUG_TRANSACTION,
|
||||
" 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);
|
||||
" 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;
|
||||
|
||||
@ -1707,19 +1696,13 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
|
||||
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);
|
||||
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",
|
||||
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;
|
||||
@ -1727,15 +1710,12 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
|
||||
file = fget(fp->handle);
|
||||
if (file == NULL) {
|
||||
binder_user_error(
|
||||
"binder: %d:%d got transaction"
|
||||
" with invalid fd, %ld\n",
|
||||
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,
|
||||
O_CLOEXEC);
|
||||
target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);
|
||||
if (target_fd < 0) {
|
||||
fput(file);
|
||||
return_error = BR_FAILED_REPLY;
|
||||
@ -1743,8 +1723,7 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
}
|
||||
task_fd_install(target_proc, target_fd, file);
|
||||
binder_debug(BINDER_DEBUG_TRANSACTION,
|
||||
" fd %ld -> %d\n", fp->handle,
|
||||
target_fd);
|
||||
" fd %ld -> %d\n", fp->handle, target_fd);
|
||||
/* TODO: fput? */
|
||||
fp->handle = target_fd;
|
||||
} break;
|
||||
@ -1893,11 +1872,9 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
|
||||
break;
|
||||
}
|
||||
binder_debug(BINDER_DEBUG_USER_REFS,
|
||||
"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);
|
||||
"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:
|
||||
@ -1958,19 +1935,17 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
|
||||
binder_debug(BINDER_DEBUG_USER_REFS,
|
||||
"binder: %d:%d %s node %d ls %d lw %d\n",
|
||||
proc->pid, thread->pid,
|
||||
cmd == BC_INCREFS_DONE ? "BC_INCREFS_DONE"
|
||||
: "BC_ACQUIRE_DONE",
|
||||
node->debug_id, node->local_strong_refs,
|
||||
node->local_weak_refs);
|
||||
cmd == BC_INCREFS_DONE ? "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE",
|
||||
node->debug_id, node->local_strong_refs, node->local_weak_refs);
|
||||
break;
|
||||
}
|
||||
case BC_ATTEMPT_ACQUIRE:
|
||||
binder_debug(BINDER_DEBUG_TOP_ERRORS,
|
||||
"binder: BC_ATTEMPT_ACQUIRE not supported\n");
|
||||
"binder: BC_ATTEMPT_ACQUIRE not supported\n");
|
||||
return -EINVAL;
|
||||
case BC_ACQUIRE_RESULT:
|
||||
binder_debug(BINDER_DEBUG_TOP_ERRORS,
|
||||
"binder: BC_ACQUIRE_RESULT not supported\n");
|
||||
binder_debug(BINDER_DEBUG_TOP_ERRORS,
|
||||
"binder: BC_ACQUIRE_RESULT not supported\n");
|
||||
return -EINVAL;
|
||||
|
||||
case BC_FREE_BUFFER: {
|
||||
@ -1996,11 +1971,9 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
|
||||
break;
|
||||
}
|
||||
binder_debug(BINDER_DEBUG_FREE_BUFFER,
|
||||
"binder: %d:%d BC_FREE_BUFFER u%p found"
|
||||
" buffer %d for %s transaction\n",
|
||||
proc->pid, thread->pid, data_ptr,
|
||||
buffer->debug_id, buffer->transaction ?
|
||||
"active" : "finished");
|
||||
"binder: %d:%d BC_FREE_BUFFER u%p found buffer %d for %s transaction\n",
|
||||
proc->pid, thread->pid, data_ptr, buffer->debug_id,
|
||||
buffer->transaction ? "active" : "finished");
|
||||
|
||||
if (buffer->transaction) {
|
||||
buffer->transaction->buffer = NULL;
|
||||
@ -2097,15 +2070,13 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
|
||||
}
|
||||
|
||||
binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
|
||||
"binder: %d:%d %s %p ref %d desc %d s %d"
|
||||
" w %d for node %d\n",
|
||||
"binder: %d:%d %s %p ref %d desc %d s %d w %d for node %d\n",
|
||||
proc->pid, thread->pid,
|
||||
cmd == BC_REQUEST_DEATH_NOTIFICATION ?
|
||||
"BC_REQUEST_DEATH_NOTIFICATION" :
|
||||
"BC_CLEAR_DEATH_NOTIFICATION",
|
||||
cookie, ref->debug_id, ref->desc,
|
||||
ref->strong, ref->weak,
|
||||
ref->node->debug_id);
|
||||
ref->strong, ref->weak, ref->node->debug_id);
|
||||
|
||||
if (cmd == BC_REQUEST_DEATH_NOTIFICATION) {
|
||||
if (ref->death) {
|
||||
@ -2119,12 +2090,10 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
|
||||
death = kzalloc(sizeof(*death), GFP_KERNEL);
|
||||
if (death == NULL) {
|
||||
thread->return_error = BR_ERROR;
|
||||
binder_debug(
|
||||
BINDER_DEBUG_FAILED_TRANSACTION,
|
||||
"binder: %d:%d "
|
||||
"BC_REQUEST_DEATH_NOTIFICATION"
|
||||
" failed\n",
|
||||
proc->pid, thread->pid);
|
||||
binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
|
||||
"binder: %d:%d "
|
||||
"BC_REQUEST_DEATH_NOTIFICATION failed\n",
|
||||
proc->pid, thread->pid);
|
||||
break;
|
||||
}
|
||||
binder_stats_created(BINDER_STAT_DEATH);
|
||||
@ -2214,8 +2183,8 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
|
||||
|
||||
default:
|
||||
binder_debug(BINDER_DEBUG_TOP_ERRORS,
|
||||
"binder: %d:%d unknown command %d\n",
|
||||
proc->pid, thread->pid, cmd);
|
||||
"binder: %d:%d unknown command %d\n",
|
||||
proc->pid, thread->pid, cmd);
|
||||
return -EINVAL;
|
||||
}
|
||||
*consumed = ptr - buffer;
|
||||
@ -2684,11 +2653,9 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
unsigned int size = _IOC_SIZE(cmd);
|
||||
void __user *ubuf = (void __user *)arg;
|
||||
|
||||
/*binder_debug(BINDER_DEBUG_TOP_ERRORS, "binder_ioctl: %d:%d %x %lx\n",
|
||||
proc->pid, current->pid, cmd, arg);*/
|
||||
/*printk(KERN_INFO "binder_ioctl: %d:%d %x %lx\n", proc->pid, current->pid, cmd, arg);*/
|
||||
|
||||
ret = wait_event_interruptible(binder_user_error_wait,
|
||||
binder_stop_on_user_error < 2);
|
||||
ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -2745,8 +2712,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
break;
|
||||
}
|
||||
case BINDER_SET_MAX_THREADS:
|
||||
if (copy_from_user(&proc->max_threads, ubuf,
|
||||
sizeof(proc->max_threads))) {
|
||||
if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) {
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
@ -2754,17 +2720,17 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
case BINDER_SET_CONTEXT_MGR:
|
||||
if (binder_context_mgr_node != NULL) {
|
||||
binder_debug(BINDER_DEBUG_TOP_ERRORS,
|
||||
"binder: BINDER_SET_CONTEXT_MGR already set\n");
|
||||
"binder: BINDER_SET_CONTEXT_MGR already set\n");
|
||||
ret = -EBUSY;
|
||||
goto err;
|
||||
}
|
||||
if (binder_context_mgr_uid != -1) {
|
||||
if (binder_context_mgr_uid != current->cred->euid) {
|
||||
binder_debug(BINDER_DEBUG_TOP_ERRORS,
|
||||
"binder: BINDER_SET_"
|
||||
"CONTEXT_MGR bad uid %d != %d\n",
|
||||
current->cred->euid,
|
||||
binder_context_mgr_uid);
|
||||
"binder: BINDER_SET_"
|
||||
"CONTEXT_MGR bad uid %d != %d\n",
|
||||
current->cred->euid,
|
||||
binder_context_mgr_uid);
|
||||
ret = -EPERM;
|
||||
goto err;
|
||||
}
|
||||
@ -2808,8 +2774,8 @@ err:
|
||||
wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
|
||||
if (ret && ret != -ERESTARTSYS)
|
||||
binder_debug(BINDER_DEBUG_TOP_ERRORS,
|
||||
"binder: %d:%d ioctl %x %lx returned %d\n",
|
||||
proc->pid, current->pid, cmd, arg, ret);
|
||||
"binder: %d:%d ioctl %x %lx returned %d\n",
|
||||
proc->pid, current->pid, cmd, arg, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2821,7 +2787,6 @@ static void binder_vma_open(struct vm_area_struct *vma)
|
||||
proc->pid, vma->vm_start, vma->vm_end,
|
||||
(vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
|
||||
(unsigned long)pgprot_val(vma->vm_page_prot));
|
||||
dump_stack();
|
||||
}
|
||||
|
||||
static void binder_vma_close(struct vm_area_struct *vma)
|
||||
@ -2833,6 +2798,7 @@ static void binder_vma_close(struct vm_area_struct *vma)
|
||||
(vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
|
||||
(unsigned long)pgprot_val(vma->vm_page_prot));
|
||||
proc->vma = NULL;
|
||||
proc->vma_vm_mm = NULL;
|
||||
binder_defer_work(proc, BINDER_DEFERRED_PUT_FILES);
|
||||
}
|
||||
|
||||
@ -2865,6 +2831,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
}
|
||||
vma->vm_flags = (vma->vm_flags | VM_DONTCOPY) & ~VM_MAYWRITE;
|
||||
|
||||
mutex_lock(&binder_mmap_lock);
|
||||
if (proc->buffer) {
|
||||
ret = -EBUSY;
|
||||
failure_string = "already mapped";
|
||||
@ -2879,13 +2846,13 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
}
|
||||
proc->buffer = area->addr;
|
||||
proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer;
|
||||
mutex_unlock(&binder_mmap_lock);
|
||||
|
||||
#ifdef CONFIG_CPU_CACHE_VIPT
|
||||
if (cache_is_vipt_aliasing()) {
|
||||
while (CACHE_COLOUR((vma->vm_start ^ (uint32_t)proc->buffer))) {
|
||||
binder_debug(BINDER_DEBUG_TOP_ERRORS,
|
||||
"binder_mmap: %d %lx-%lx maps %p bad alignment\n",
|
||||
proc->pid, vma->vm_start, vma->vm_end, proc->buffer);
|
||||
"binder_mmap: %d %lx-%lx maps %p bad alignment\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer);
|
||||
vma->vm_start += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
@ -2913,11 +2880,11 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
binder_insert_free_buffer(proc, buffer);
|
||||
proc->free_async_space = proc->buffer_size / 2;
|
||||
barrier();
|
||||
proc->files = get_files_struct(current);
|
||||
proc->files = get_files_struct(proc->tsk);
|
||||
proc->vma = vma;
|
||||
proc->vma_vm_mm = vma->vm_mm;
|
||||
|
||||
/*binder_debug(BINDER_DEBUG_TOP_ERRORS,
|
||||
"binder_mmap: %d %lx-%lx maps %p\n",
|
||||
/*printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p\n",
|
||||
proc->pid, vma->vm_start, vma->vm_end, proc->buffer);*/
|
||||
return 0;
|
||||
|
||||
@ -2925,14 +2892,17 @@ err_alloc_small_buf_failed:
|
||||
kfree(proc->pages);
|
||||
proc->pages = NULL;
|
||||
err_alloc_pages_failed:
|
||||
mutex_lock(&binder_mmap_lock);
|
||||
vfree(proc->buffer);
|
||||
proc->buffer = NULL;
|
||||
err_get_vm_area_failed:
|
||||
err_already_mapped:
|
||||
mutex_unlock(&binder_mmap_lock);
|
||||
err_bad_arg:
|
||||
binder_debug(BINDER_DEBUG_TOP_ERRORS,
|
||||
"binder_mmap: %d %lx-%lx %s failed %d\n",
|
||||
proc->pid, vma->vm_start, vma->vm_end, failure_string, ret);
|
||||
"binder_mmap: %d %lx-%lx %s failed %d\n",
|
||||
proc->pid, vma->vm_start, vma->vm_end, failure_string,
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -3087,9 +3057,9 @@ static void binder_deferred_release(struct binder_proc *proc)
|
||||
t->buffer = NULL;
|
||||
buffer->transaction = NULL;
|
||||
binder_debug(BINDER_DEBUG_TOP_ERRORS,
|
||||
"binder: release proc %d, "
|
||||
"transaction %d, not freed\n",
|
||||
proc->pid, t->debug_id);
|
||||
"binder: release proc %d, "
|
||||
"transaction %d, not freed\n",
|
||||
proc->pid, t->debug_id);
|
||||
/*BUG();*/
|
||||
}
|
||||
binder_free_buf(proc, buffer);
|
||||
|
Loading…
x
Reference in New Issue
Block a user