|
@@ -118,6 +118,7 @@ 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);
|
|
@@ -194,6 +195,7 @@ 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++;
|
|
@@ -432,6 +434,7 @@ static inline void binder_unlock(const char *tag)
|
|
|
static void binder_set_nice(long nice)
|
|
|
{
|
|
|
long min_nice;
|
|
|
+
|
|
|
if (can_nice(current, nice)) {
|
|
|
set_user_nice(current, nice);
|
|
|
return;
|
|
@@ -584,6 +587,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
|
|
|
for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) {
|
|
|
int ret;
|
|
|
struct page **page_array_ptr;
|
|
|
+
|
|
|
page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];
|
|
|
|
|
|
BUG_ON(*page);
|
|
@@ -726,6 +730,7 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,
|
|
|
binder_insert_allocated_buffer(proc, buffer);
|
|
|
if (buffer_size != size) {
|
|
|
struct binder_buffer *new_buffer = (void *)buffer->data + size;
|
|
|
+
|
|
|
list_add(&new_buffer->entry, &buffer->entry);
|
|
|
new_buffer->free = 1;
|
|
|
binder_insert_free_buffer(proc, new_buffer);
|
|
@@ -838,6 +843,7 @@ static void binder_free_buf(struct binder_proc *proc,
|
|
|
if (!list_is_last(&buffer->entry, &proc->buffers)) {
|
|
|
struct binder_buffer *next = list_entry(buffer->entry.next,
|
|
|
struct binder_buffer, entry);
|
|
|
+
|
|
|
if (next->free) {
|
|
|
rb_erase(&next->rb_node, &proc->free_buffers);
|
|
|
binder_delete_free_buffer(proc, next);
|
|
@@ -846,6 +852,7 @@ static void binder_free_buf(struct binder_proc *proc,
|
|
|
if (proc->buffers.next != &buffer->entry) {
|
|
|
struct binder_buffer *prev = list_entry(buffer->entry.prev,
|
|
|
struct binder_buffer, entry);
|
|
|
+
|
|
|
if (prev->free) {
|
|
|
binder_delete_free_buffer(proc, buffer);
|
|
|
rb_erase(&prev->rb_node, &proc->free_buffers);
|
|
@@ -1107,6 +1114,7 @@ static int binder_inc_ref(struct binder_ref *ref, int strong,
|
|
|
struct list_head *target_list)
|
|
|
{
|
|
|
int ret;
|
|
|
+
|
|
|
if (strong) {
|
|
|
if (ref->strong == 0) {
|
|
|
ret = binder_inc_node(ref->node, 1, 1, target_list);
|
|
@@ -1138,6 +1146,7 @@ static int binder_dec_ref(struct binder_ref *ref, int strong)
|
|
|
ref->strong--;
|
|
|
if (ref->strong == 0) {
|
|
|
int ret;
|
|
|
+
|
|
|
ret = binder_dec_node(ref->node, strong, 1);
|
|
|
if (ret)
|
|
|
return ret;
|
|
@@ -1177,6 +1186,7 @@ static void binder_send_failed_reply(struct binder_transaction *t,
|
|
|
uint32_t error_code)
|
|
|
{
|
|
|
struct binder_thread *target_thread;
|
|
|
+
|
|
|
BUG_ON(t->flags & TF_ONE_WAY);
|
|
|
while (1) {
|
|
|
target_thread = t->from;
|
|
@@ -1247,6 +1257,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
|
|
|
off_end = (void *)offp + buffer->offsets_size;
|
|
|
for (; offp < off_end; offp++) {
|
|
|
struct flat_binder_object *fp;
|
|
|
+
|
|
|
if (*offp > buffer->data_size - sizeof(*fp) ||
|
|
|
buffer->data_size < sizeof(*fp) ||
|
|
|
!IS_ALIGNED(*offp, sizeof(u32))) {
|
|
@@ -1259,6 +1270,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
|
|
|
case BINDER_TYPE_BINDER:
|
|
|
case BINDER_TYPE_WEAK_BINDER: {
|
|
|
struct binder_node *node = binder_get_node(proc, fp->binder);
|
|
|
+
|
|
|
if (node == NULL) {
|
|
|
pr_err("transaction release %d bad node %016llx\n",
|
|
|
debug_id, (u64)fp->binder);
|
|
@@ -1272,6 +1284,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
|
|
|
case BINDER_TYPE_HANDLE:
|
|
|
case BINDER_TYPE_WEAK_HANDLE: {
|
|
|
struct binder_ref *ref = binder_get_ref(proc, fp->handle);
|
|
|
+
|
|
|
if (ref == NULL) {
|
|
|
pr_err("transaction release %d bad handle %d\n",
|
|
|
debug_id, fp->handle);
|
|
@@ -1363,6 +1376,7 @@ static void binder_transaction(struct binder_proc *proc,
|
|
|
} else {
|
|
|
if (tr->target.handle) {
|
|
|
struct binder_ref *ref;
|
|
|
+
|
|
|
ref = binder_get_ref(proc, tr->target.handle);
|
|
|
if (ref == NULL) {
|
|
|
binder_user_error("%d:%d got transaction to invalid handle\n",
|
|
@@ -1386,6 +1400,7 @@ static void binder_transaction(struct binder_proc *proc,
|
|
|
}
|
|
|
if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) {
|
|
|
struct binder_transaction *tmp;
|
|
|
+
|
|
|
tmp = thread->transaction_stack;
|
|
|
if (tmp->to_thread != thread) {
|
|
|
binder_user_error("%d:%d got new transaction with bad transaction stack, transaction %d has target %d:%d\n",
|
|
@@ -1501,6 +1516,7 @@ static void binder_transaction(struct binder_proc *proc,
|
|
|
off_end = (void *)offp + tr->offsets_size;
|
|
|
for (; offp < off_end; offp++) {
|
|
|
struct flat_binder_object *fp;
|
|
|
+
|
|
|
if (*offp > t->buffer->data_size - sizeof(*fp) ||
|
|
|
t->buffer->data_size < sizeof(*fp) ||
|
|
|
!IS_ALIGNED(*offp, sizeof(u32))) {
|
|
@@ -1515,6 +1531,7 @@ static void binder_transaction(struct binder_proc *proc,
|
|
|
case BINDER_TYPE_WEAK_BINDER: {
|
|
|
struct binder_ref *ref;
|
|
|
struct binder_node *node = binder_get_node(proc, fp->binder);
|
|
|
+
|
|
|
if (node == NULL) {
|
|
|
node = binder_new_node(proc, fp->binder, fp->cookie);
|
|
|
if (node == NULL) {
|
|
@@ -1553,6 +1570,7 @@ static void binder_transaction(struct binder_proc *proc,
|
|
|
case BINDER_TYPE_HANDLE:
|
|
|
case BINDER_TYPE_WEAK_HANDLE: {
|
|
|
struct binder_ref *ref = binder_get_ref(proc, fp->handle);
|
|
|
+
|
|
|
if (ref == NULL) {
|
|
|
binder_user_error("%d:%d got transaction with invalid handle, %d\n",
|
|
|
proc->pid,
|
|
@@ -1575,6 +1593,7 @@ static void binder_transaction(struct binder_proc *proc,
|
|
|
(u64)ref->node->ptr);
|
|
|
} else {
|
|
|
struct binder_ref *new_ref;
|
|
|
+
|
|
|
new_ref = binder_get_ref_for_node(target_proc, ref->node);
|
|
|
if (new_ref == NULL) {
|
|
|
return_error = BR_FAILED_REPLY;
|
|
@@ -1694,6 +1713,7 @@ err_no_context_mgr_node:
|
|
|
|
|
|
{
|
|
|
struct binder_transaction_log_entry *fe;
|
|
|
+
|
|
|
fe = binder_transaction_log_add(&binder_transaction_log_failed);
|
|
|
*fe = *e;
|
|
|
}
|
|
@@ -2024,12 +2044,14 @@ static int binder_thread_write(struct binder_proc *proc,
|
|
|
struct binder_work *w;
|
|
|
binder_uintptr_t cookie;
|
|
|
struct binder_ref_death *death = NULL;
|
|
|
+
|
|
|
if (get_user(cookie, (binder_uintptr_t __user *)ptr))
|
|
|
return -EFAULT;
|
|
|
|
|
|
ptr += sizeof(void *);
|
|
|
list_for_each_entry(w, &proc->delivered_death, entry) {
|
|
|
struct binder_ref_death *tmp_death = container_of(w, struct binder_ref_death, work);
|
|
|
+
|
|
|
if (tmp_death->cookie == cookie) {
|
|
|
death = tmp_death;
|
|
|
break;
|
|
@@ -2216,6 +2238,7 @@ retry:
|
|
|
const char *cmd_name;
|
|
|
int strong = node->internal_strong_refs || node->local_strong_refs;
|
|
|
int weak = !hlist_empty(&node->refs) || node->local_weak_refs || strong;
|
|
|
+
|
|
|
if (weak && !node->has_weak_ref) {
|
|
|
cmd = BR_INCREFS;
|
|
|
cmd_name = "BR_INCREFS";
|
|
@@ -2322,6 +2345,7 @@ retry:
|
|
|
BUG_ON(t->buffer == NULL);
|
|
|
if (t->buffer->target_node) {
|
|
|
struct binder_node *target_node = t->buffer->target_node;
|
|
|
+
|
|
|
tr.target.ptr = target_node->ptr;
|
|
|
tr.cookie = target_node->cookie;
|
|
|
t->saved_priority = task_nice(current);
|
|
@@ -2343,6 +2367,7 @@ retry:
|
|
|
|
|
|
if (t->from) {
|
|
|
struct task_struct *sender = t->from->proc->tsk;
|
|
|
+
|
|
|
tr.sender_pid = task_tgid_nr_ns(sender,
|
|
|
task_active_pid_ns(current));
|
|
|
} else {
|
|
@@ -2413,6 +2438,7 @@ done:
|
|
|
static void binder_release_work(struct list_head *list)
|
|
|
{
|
|
|
struct binder_work *w;
|
|
|
+
|
|
|
while (!list_empty(list)) {
|
|
|
w = list_first_entry(list, struct binder_work, entry);
|
|
|
list_del_init(&w->entry);
|
|
@@ -2593,6 +2619,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
|
|
switch (cmd) {
|
|
|
case BINDER_WRITE_READ: {
|
|
|
struct binder_write_read bwr;
|
|
|
+
|
|
|
if (size != sizeof(struct binder_write_read)) {
|
|
|
ret = -EINVAL;
|
|
|
goto err;
|
|
@@ -2717,6 +2744,7 @@ err_unlocked:
|
|
|
static void binder_vma_open(struct vm_area_struct *vma)
|
|
|
{
|
|
|
struct binder_proc *proc = vma->vm_private_data;
|
|
|
+
|
|
|
binder_debug(BINDER_DEBUG_OPEN_CLOSE,
|
|
|
"%d open vm area %lx-%lx (%ld K) vma %lx pagep %lx\n",
|
|
|
proc->pid, vma->vm_start, vma->vm_end,
|
|
@@ -2727,6 +2755,7 @@ static void binder_vma_open(struct vm_area_struct *vma)
|
|
|
static void binder_vma_close(struct vm_area_struct *vma)
|
|
|
{
|
|
|
struct binder_proc *proc = vma->vm_private_data;
|
|
|
+
|
|
|
binder_debug(BINDER_DEBUG_OPEN_CLOSE,
|
|
|
"%d close vm area %lx-%lx (%ld K) vma %lx pagep %lx\n",
|
|
|
proc->pid, vma->vm_start, vma->vm_end,
|
|
@@ -2869,6 +2898,7 @@ static int binder_open(struct inode *nodp, struct file *filp)
|
|
|
|
|
|
if (binder_debugfs_dir_entry_proc) {
|
|
|
char strbuf[11];
|
|
|
+
|
|
|
snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
|
|
|
proc->debugfs_entry = debugfs_create_file(strbuf, S_IRUGO,
|
|
|
binder_debugfs_dir_entry_proc, proc, &binder_proc_fops);
|
|
@@ -2890,8 +2920,10 @@ static void binder_deferred_flush(struct binder_proc *proc)
|
|
|
{
|
|
|
struct rb_node *n;
|
|
|
int wake_count = 0;
|
|
|
+
|
|
|
for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) {
|
|
|
struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node);
|
|
|
+
|
|
|
thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN;
|
|
|
if (thread->looper & BINDER_LOOPER_STATE_WAITING) {
|
|
|
wake_up_interruptible(&thread->wait);
|
|
@@ -2908,6 +2940,7 @@ static void binder_deferred_flush(struct binder_proc *proc)
|
|
|
static int binder_release(struct inode *nodp, struct file *filp)
|
|
|
{
|
|
|
struct binder_proc *proc = filp->private_data;
|
|
|
+
|
|
|
debugfs_remove(proc->debugfs_entry);
|
|
|
binder_defer_work(proc, BINDER_DEFERRED_RELEASE);
|
|
|
|
|
@@ -3069,6 +3102,7 @@ static void binder_deferred_func(struct work_struct *work)
|
|
|
struct files_struct *files;
|
|
|
|
|
|
int defer;
|
|
|
+
|
|
|
do {
|
|
|
binder_lock(__func__);
|
|
|
mutex_lock(&binder_deferred_lock);
|