diff options
author | Todd Kjos <tkjos@android.com> | 2017-06-29 15:01:43 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-07-17 08:47:29 -0400 |
commit | c44b1231ff1170971c1f27fc33a8cc3188de99cb (patch) | |
tree | 596016811d0f20e3a0672795b8c8a0bb5847be2c | |
parent | 1cf29cf4295ad2dc2009b421702ba4197b85acfd (diff) |
binder: add protection for non-perf cases
Add binder_dead_nodes_lock, binder_procs_lock, and
binder_context_mgr_node_lock to protect the associated global lists
Signed-off-by: Todd Kjos <tkjos@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/android/binder.c | 81 |
1 files changed, 63 insertions, 18 deletions
diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 10fda7ab9fa5..fb484c6acd3e 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c | |||
@@ -46,12 +46,16 @@ | |||
46 | #include "binder_trace.h" | 46 | #include "binder_trace.h" |
47 | 47 | ||
48 | static DEFINE_MUTEX(binder_main_lock); | 48 | static DEFINE_MUTEX(binder_main_lock); |
49 | |||
50 | static HLIST_HEAD(binder_deferred_list); | ||
49 | static DEFINE_MUTEX(binder_deferred_lock); | 51 | static DEFINE_MUTEX(binder_deferred_lock); |
50 | 52 | ||
51 | static HLIST_HEAD(binder_devices); | 53 | static HLIST_HEAD(binder_devices); |
52 | static HLIST_HEAD(binder_procs); | 54 | static HLIST_HEAD(binder_procs); |
53 | static HLIST_HEAD(binder_deferred_list); | 55 | static DEFINE_MUTEX(binder_procs_lock); |
56 | |||
54 | static HLIST_HEAD(binder_dead_nodes); | 57 | static HLIST_HEAD(binder_dead_nodes); |
58 | static DEFINE_SPINLOCK(binder_dead_nodes_lock); | ||
55 | 59 | ||
56 | static struct dentry *binder_debugfs_dir_entry_root; | 60 | static struct dentry *binder_debugfs_dir_entry_root; |
57 | static struct dentry *binder_debugfs_dir_entry_proc; | 61 | static struct dentry *binder_debugfs_dir_entry_proc; |
@@ -219,6 +223,8 @@ static struct binder_transaction_log_entry *binder_transaction_log_add( | |||
219 | 223 | ||
220 | struct binder_context { | 224 | struct binder_context { |
221 | struct binder_node *binder_context_mgr_node; | 225 | struct binder_node *binder_context_mgr_node; |
226 | struct mutex context_mgr_node_lock; | ||
227 | |||
222 | kuid_t binder_context_mgr_uid; | 228 | kuid_t binder_context_mgr_uid; |
223 | const char *name; | 229 | const char *name; |
224 | }; | 230 | }; |
@@ -570,7 +576,9 @@ static int binder_dec_node(struct binder_node *node, int strong, int internal) | |||
570 | "refless node %d deleted\n", | 576 | "refless node %d deleted\n", |
571 | node->debug_id); | 577 | node->debug_id); |
572 | } else { | 578 | } else { |
579 | spin_lock(&binder_dead_nodes_lock); | ||
573 | hlist_del(&node->dead_node); | 580 | hlist_del(&node->dead_node); |
581 | spin_unlock(&binder_dead_nodes_lock); | ||
574 | binder_debug(BINDER_DEBUG_INTERNAL_REFS, | 582 | binder_debug(BINDER_DEBUG_INTERNAL_REFS, |
575 | "dead node %d deleted\n", | 583 | "dead node %d deleted\n", |
576 | node->debug_id); | 584 | node->debug_id); |
@@ -1454,11 +1462,14 @@ static void binder_transaction(struct binder_proc *proc, | |||
1454 | } | 1462 | } |
1455 | target_node = ref->node; | 1463 | target_node = ref->node; |
1456 | } else { | 1464 | } else { |
1465 | mutex_lock(&context->context_mgr_node_lock); | ||
1457 | target_node = context->binder_context_mgr_node; | 1466 | target_node = context->binder_context_mgr_node; |
1458 | if (target_node == NULL) { | 1467 | if (target_node == NULL) { |
1459 | return_error = BR_DEAD_REPLY; | 1468 | return_error = BR_DEAD_REPLY; |
1469 | mutex_unlock(&context->context_mgr_node_lock); | ||
1460 | goto err_no_context_mgr_node; | 1470 | goto err_no_context_mgr_node; |
1461 | } | 1471 | } |
1472 | mutex_unlock(&context->context_mgr_node_lock); | ||
1462 | } | 1473 | } |
1463 | e->to_node = target_node->debug_id; | 1474 | e->to_node = target_node->debug_id; |
1464 | target_proc = target_node->proc; | 1475 | target_proc = target_node->proc; |
@@ -1824,22 +1835,31 @@ static int binder_thread_write(struct binder_proc *proc, | |||
1824 | case BC_RELEASE: | 1835 | case BC_RELEASE: |
1825 | case BC_DECREFS: { | 1836 | case BC_DECREFS: { |
1826 | uint32_t target; | 1837 | uint32_t target; |
1827 | struct binder_ref *ref; | 1838 | struct binder_ref *ref = NULL; |
1828 | const char *debug_string; | 1839 | const char *debug_string; |
1829 | 1840 | ||
1830 | if (get_user(target, (uint32_t __user *)ptr)) | 1841 | if (get_user(target, (uint32_t __user *)ptr)) |
1831 | return -EFAULT; | 1842 | return -EFAULT; |
1843 | |||
1832 | ptr += sizeof(uint32_t); | 1844 | ptr += sizeof(uint32_t); |
1833 | if (target == 0 && context->binder_context_mgr_node && | 1845 | if (target == 0 && |
1834 | (cmd == BC_INCREFS || cmd == BC_ACQUIRE)) { | 1846 | (cmd == BC_INCREFS || cmd == BC_ACQUIRE)) { |
1835 | ref = binder_get_ref_for_node(proc, | 1847 | struct binder_node *ctx_mgr_node; |
1836 | context->binder_context_mgr_node); | 1848 | |
1837 | if (ref->desc != target) { | 1849 | mutex_lock(&context->context_mgr_node_lock); |
1838 | binder_user_error("%d:%d tried to acquire reference to desc 0, got %d instead\n", | 1850 | ctx_mgr_node = context->binder_context_mgr_node; |
1839 | proc->pid, thread->pid, | 1851 | if (ctx_mgr_node) { |
1840 | ref->desc); | 1852 | ref = binder_get_ref_for_node(proc, |
1853 | ctx_mgr_node); | ||
1854 | if (ref && ref->desc != target) { | ||
1855 | binder_user_error("%d:%d tried to acquire reference to desc 0, got %d instead\n", | ||
1856 | proc->pid, thread->pid, | ||
1857 | ref->desc); | ||
1858 | } | ||
1841 | } | 1859 | } |
1842 | } else | 1860 | mutex_unlock(&context->context_mgr_node_lock); |
1861 | } | ||
1862 | if (ref == NULL) | ||
1843 | ref = binder_get_ref(proc, target, | 1863 | ref = binder_get_ref(proc, target, |
1844 | cmd == BC_ACQUIRE || | 1864 | cmd == BC_ACQUIRE || |
1845 | cmd == BC_RELEASE); | 1865 | cmd == BC_RELEASE); |
@@ -2753,9 +2773,10 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp) | |||
2753 | int ret = 0; | 2773 | int ret = 0; |
2754 | struct binder_proc *proc = filp->private_data; | 2774 | struct binder_proc *proc = filp->private_data; |
2755 | struct binder_context *context = proc->context; | 2775 | struct binder_context *context = proc->context; |
2756 | 2776 | struct binder_node *new_node; | |
2757 | kuid_t curr_euid = current_euid(); | 2777 | kuid_t curr_euid = current_euid(); |
2758 | 2778 | ||
2779 | mutex_lock(&context->context_mgr_node_lock); | ||
2759 | if (context->binder_context_mgr_node) { | 2780 | if (context->binder_context_mgr_node) { |
2760 | pr_err("BINDER_SET_CONTEXT_MGR already set\n"); | 2781 | pr_err("BINDER_SET_CONTEXT_MGR already set\n"); |
2761 | ret = -EBUSY; | 2782 | ret = -EBUSY; |
@@ -2776,16 +2797,18 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp) | |||
2776 | } else { | 2797 | } else { |
2777 | context->binder_context_mgr_uid = curr_euid; | 2798 | context->binder_context_mgr_uid = curr_euid; |
2778 | } | 2799 | } |
2779 | context->binder_context_mgr_node = binder_new_node(proc, 0, 0); | 2800 | new_node = binder_new_node(proc, 0, 0); |
2780 | if (!context->binder_context_mgr_node) { | 2801 | if (!new_node) { |
2781 | ret = -ENOMEM; | 2802 | ret = -ENOMEM; |
2782 | goto out; | 2803 | goto out; |
2783 | } | 2804 | } |
2784 | context->binder_context_mgr_node->local_weak_refs++; | 2805 | new_node->local_weak_refs++; |
2785 | context->binder_context_mgr_node->local_strong_refs++; | 2806 | new_node->local_strong_refs++; |
2786 | context->binder_context_mgr_node->has_strong_ref = 1; | 2807 | new_node->has_strong_ref = 1; |
2787 | context->binder_context_mgr_node->has_weak_ref = 1; | 2808 | new_node->has_weak_ref = 1; |
2809 | context->binder_context_mgr_node = new_node; | ||
2788 | out: | 2810 | out: |
2811 | mutex_unlock(&context->context_mgr_node_lock); | ||
2789 | return ret; | 2812 | return ret; |
2790 | } | 2813 | } |
2791 | 2814 | ||
@@ -2965,13 +2988,16 @@ static int binder_open(struct inode *nodp, struct file *filp) | |||
2965 | binder_lock(__func__); | 2988 | binder_lock(__func__); |
2966 | 2989 | ||
2967 | binder_stats_created(BINDER_STAT_PROC); | 2990 | binder_stats_created(BINDER_STAT_PROC); |
2968 | hlist_add_head(&proc->proc_node, &binder_procs); | ||
2969 | proc->pid = current->group_leader->pid; | 2991 | proc->pid = current->group_leader->pid; |
2970 | INIT_LIST_HEAD(&proc->delivered_death); | 2992 | INIT_LIST_HEAD(&proc->delivered_death); |
2971 | filp->private_data = proc; | 2993 | filp->private_data = proc; |
2972 | 2994 | ||
2973 | binder_unlock(__func__); | 2995 | binder_unlock(__func__); |
2974 | 2996 | ||
2997 | mutex_lock(&binder_procs_lock); | ||
2998 | hlist_add_head(&proc->proc_node, &binder_procs); | ||
2999 | mutex_unlock(&binder_procs_lock); | ||
3000 | |||
2975 | if (binder_debugfs_dir_entry_proc) { | 3001 | if (binder_debugfs_dir_entry_proc) { |
2976 | char strbuf[11]; | 3002 | char strbuf[11]; |
2977 | 3003 | ||
@@ -3050,7 +3076,10 @@ static int binder_node_release(struct binder_node *node, int refs) | |||
3050 | node->proc = NULL; | 3076 | node->proc = NULL; |
3051 | node->local_strong_refs = 0; | 3077 | node->local_strong_refs = 0; |
3052 | node->local_weak_refs = 0; | 3078 | node->local_weak_refs = 0; |
3079 | |||
3080 | spin_lock(&binder_dead_nodes_lock); | ||
3053 | hlist_add_head(&node->dead_node, &binder_dead_nodes); | 3081 | hlist_add_head(&node->dead_node, &binder_dead_nodes); |
3082 | spin_unlock(&binder_dead_nodes_lock); | ||
3054 | 3083 | ||
3055 | hlist_for_each_entry(ref, &node->refs, node_entry) { | 3084 | hlist_for_each_entry(ref, &node->refs, node_entry) { |
3056 | refs++; | 3085 | refs++; |
@@ -3084,8 +3113,11 @@ static void binder_deferred_release(struct binder_proc *proc) | |||
3084 | 3113 | ||
3085 | BUG_ON(proc->files); | 3114 | BUG_ON(proc->files); |
3086 | 3115 | ||
3116 | mutex_lock(&binder_procs_lock); | ||
3087 | hlist_del(&proc->proc_node); | 3117 | hlist_del(&proc->proc_node); |
3118 | mutex_unlock(&binder_procs_lock); | ||
3088 | 3119 | ||
3120 | mutex_lock(&context->context_mgr_node_lock); | ||
3089 | if (context->binder_context_mgr_node && | 3121 | if (context->binder_context_mgr_node && |
3090 | context->binder_context_mgr_node->proc == proc) { | 3122 | context->binder_context_mgr_node->proc == proc) { |
3091 | binder_debug(BINDER_DEBUG_DEAD_BINDER, | 3123 | binder_debug(BINDER_DEBUG_DEAD_BINDER, |
@@ -3093,6 +3125,7 @@ static void binder_deferred_release(struct binder_proc *proc) | |||
3093 | __func__, proc->pid); | 3125 | __func__, proc->pid); |
3094 | context->binder_context_mgr_node = NULL; | 3126 | context->binder_context_mgr_node = NULL; |
3095 | } | 3127 | } |
3128 | mutex_unlock(&context->context_mgr_node_lock); | ||
3096 | 3129 | ||
3097 | threads = 0; | 3130 | threads = 0; |
3098 | active_transactions = 0; | 3131 | active_transactions = 0; |
@@ -3509,13 +3542,17 @@ static int binder_state_show(struct seq_file *m, void *unused) | |||
3509 | 3542 | ||
3510 | seq_puts(m, "binder state:\n"); | 3543 | seq_puts(m, "binder state:\n"); |
3511 | 3544 | ||
3545 | spin_lock(&binder_dead_nodes_lock); | ||
3512 | if (!hlist_empty(&binder_dead_nodes)) | 3546 | if (!hlist_empty(&binder_dead_nodes)) |
3513 | seq_puts(m, "dead nodes:\n"); | 3547 | seq_puts(m, "dead nodes:\n"); |
3514 | hlist_for_each_entry(node, &binder_dead_nodes, dead_node) | 3548 | hlist_for_each_entry(node, &binder_dead_nodes, dead_node) |
3515 | print_binder_node(m, node); | 3549 | print_binder_node(m, node); |
3550 | spin_unlock(&binder_dead_nodes_lock); | ||
3516 | 3551 | ||
3552 | mutex_lock(&binder_procs_lock); | ||
3517 | hlist_for_each_entry(proc, &binder_procs, proc_node) | 3553 | hlist_for_each_entry(proc, &binder_procs, proc_node) |
3518 | print_binder_proc(m, proc, 1); | 3554 | print_binder_proc(m, proc, 1); |
3555 | mutex_unlock(&binder_procs_lock); | ||
3519 | binder_unlock(__func__); | 3556 | binder_unlock(__func__); |
3520 | return 0; | 3557 | return 0; |
3521 | } | 3558 | } |
@@ -3530,8 +3567,10 @@ static int binder_stats_show(struct seq_file *m, void *unused) | |||
3530 | 3567 | ||
3531 | print_binder_stats(m, "", &binder_stats); | 3568 | print_binder_stats(m, "", &binder_stats); |
3532 | 3569 | ||
3570 | mutex_lock(&binder_procs_lock); | ||
3533 | hlist_for_each_entry(proc, &binder_procs, proc_node) | 3571 | hlist_for_each_entry(proc, &binder_procs, proc_node) |
3534 | print_binder_proc_stats(m, proc); | 3572 | print_binder_proc_stats(m, proc); |
3573 | mutex_unlock(&binder_procs_lock); | ||
3535 | binder_unlock(__func__); | 3574 | binder_unlock(__func__); |
3536 | return 0; | 3575 | return 0; |
3537 | } | 3576 | } |
@@ -3543,8 +3582,10 @@ static int binder_transactions_show(struct seq_file *m, void *unused) | |||
3543 | binder_lock(__func__); | 3582 | binder_lock(__func__); |
3544 | 3583 | ||
3545 | seq_puts(m, "binder transactions:\n"); | 3584 | seq_puts(m, "binder transactions:\n"); |
3585 | mutex_lock(&binder_procs_lock); | ||
3546 | hlist_for_each_entry(proc, &binder_procs, proc_node) | 3586 | hlist_for_each_entry(proc, &binder_procs, proc_node) |
3547 | print_binder_proc(m, proc, 0); | 3587 | print_binder_proc(m, proc, 0); |
3588 | mutex_unlock(&binder_procs_lock); | ||
3548 | binder_unlock(__func__); | 3589 | binder_unlock(__func__); |
3549 | return 0; | 3590 | return 0; |
3550 | } | 3591 | } |
@@ -3556,12 +3597,15 @@ static int binder_proc_show(struct seq_file *m, void *unused) | |||
3556 | 3597 | ||
3557 | binder_lock(__func__); | 3598 | binder_lock(__func__); |
3558 | 3599 | ||
3600 | mutex_lock(&binder_procs_lock); | ||
3559 | hlist_for_each_entry(itr, &binder_procs, proc_node) { | 3601 | hlist_for_each_entry(itr, &binder_procs, proc_node) { |
3560 | if (itr->pid == pid) { | 3602 | if (itr->pid == pid) { |
3561 | seq_puts(m, "binder proc state:\n"); | 3603 | seq_puts(m, "binder proc state:\n"); |
3562 | print_binder_proc(m, itr, 1); | 3604 | print_binder_proc(m, itr, 1); |
3563 | } | 3605 | } |
3564 | } | 3606 | } |
3607 | mutex_unlock(&binder_procs_lock); | ||
3608 | |||
3565 | binder_unlock(__func__); | 3609 | binder_unlock(__func__); |
3566 | return 0; | 3610 | return 0; |
3567 | } | 3611 | } |
@@ -3622,6 +3666,7 @@ static int __init init_binder_device(const char *name) | |||
3622 | 3666 | ||
3623 | binder_device->context.binder_context_mgr_uid = INVALID_UID; | 3667 | binder_device->context.binder_context_mgr_uid = INVALID_UID; |
3624 | binder_device->context.name = name; | 3668 | binder_device->context.name = name; |
3669 | mutex_init(&binder_device->context.context_mgr_node_lock); | ||
3625 | 3670 | ||
3626 | ret = misc_register(&binder_device->miscdev); | 3671 | ret = misc_register(&binder_device->miscdev); |
3627 | if (ret < 0) { | 3672 | if (ret < 0) { |