diff options
author | Martijn Coenen <maco@google.com> | 2017-02-03 17:40:46 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-02-10 10:00:01 -0500 |
commit | 342e5c90b60134ddd6e4d59e521b6aa66b75bdad (patch) | |
tree | 9d8852e540c0cb23bb67065b721d9cae8a36c226 | |
parent | feba3900cabb8e7c87368faa28e7a6936809ba22 (diff) |
binder: Support multiple context managers
Move the context manager state into a separate
struct context, and allow for each process to have
its own context associated with it.
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Martijn Coenen <maco@google.com>
Cc: Arve Hjønnevåg <arve@android.com>
Cc: Amit Pundir <amit.pundir@linaro.org>
Cc: Serban Constantinescu <serban.constantinescu@arm.com>
Cc: Dmitry Shmidt <dimitrysh@google.com>
Cc: Rom Lemarchand <romlem@google.com>
Cc: Android Kernel Team <kernel-team@android.com>
Signed-off-by: Martijn Coenen <maco@google.com>
[jstultz: Minor checkpatch fix]
Signed-off-by: John Stultz <john.stultz@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/android/binder.c | 59 |
1 files changed, 38 insertions, 21 deletions
diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 331d2abca9a2..59cb6d9ddbc0 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c | |||
@@ -56,8 +56,6 @@ static HLIST_HEAD(binder_dead_nodes); | |||
56 | 56 | ||
57 | static struct dentry *binder_debugfs_dir_entry_root; | 57 | static struct dentry *binder_debugfs_dir_entry_root; |
58 | static struct dentry *binder_debugfs_dir_entry_proc; | 58 | static struct dentry *binder_debugfs_dir_entry_proc; |
59 | static struct binder_node *binder_context_mgr_node; | ||
60 | static kuid_t binder_context_mgr_uid = INVALID_UID; | ||
61 | static int binder_last_id; | 59 | static int binder_last_id; |
62 | 60 | ||
63 | #define BINDER_DEBUG_ENTRY(name) \ | 61 | #define BINDER_DEBUG_ENTRY(name) \ |
@@ -215,6 +213,15 @@ static struct binder_transaction_log_entry *binder_transaction_log_add( | |||
215 | return e; | 213 | return e; |
216 | } | 214 | } |
217 | 215 | ||
216 | struct binder_context { | ||
217 | struct binder_node *binder_context_mgr_node; | ||
218 | kuid_t binder_context_mgr_uid; | ||
219 | }; | ||
220 | |||
221 | static struct binder_context global_context = { | ||
222 | .binder_context_mgr_uid = INVALID_UID, | ||
223 | }; | ||
224 | |||
218 | struct binder_work { | 225 | struct binder_work { |
219 | struct list_head entry; | 226 | struct list_head entry; |
220 | enum { | 227 | enum { |
@@ -330,6 +337,7 @@ struct binder_proc { | |||
330 | int ready_threads; | 337 | int ready_threads; |
331 | long default_priority; | 338 | long default_priority; |
332 | struct dentry *debugfs_entry; | 339 | struct dentry *debugfs_entry; |
340 | struct binder_context *context; | ||
333 | }; | 341 | }; |
334 | 342 | ||
335 | enum { | 343 | enum { |
@@ -934,8 +942,9 @@ static int binder_inc_node(struct binder_node *node, int strong, int internal, | |||
934 | if (internal) { | 942 | if (internal) { |
935 | if (target_list == NULL && | 943 | if (target_list == NULL && |
936 | node->internal_strong_refs == 0 && | 944 | node->internal_strong_refs == 0 && |
937 | !(node == binder_context_mgr_node && | 945 | !(node->proc && |
938 | node->has_strong_ref)) { | 946 | node == node->proc->context->binder_context_mgr_node && |
947 | node->has_strong_ref)) { | ||
939 | pr_err("invalid inc strong node for %d\n", | 948 | pr_err("invalid inc strong node for %d\n", |
940 | node->debug_id); | 949 | node->debug_id); |
941 | return -EINVAL; | 950 | return -EINVAL; |
@@ -1036,6 +1045,7 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc, | |||
1036 | struct rb_node **p = &proc->refs_by_node.rb_node; | 1045 | struct rb_node **p = &proc->refs_by_node.rb_node; |
1037 | struct rb_node *parent = NULL; | 1046 | struct rb_node *parent = NULL; |
1038 | struct binder_ref *ref, *new_ref; | 1047 | struct binder_ref *ref, *new_ref; |
1048 | struct binder_context *context = proc->context; | ||
1039 | 1049 | ||
1040 | while (*p) { | 1050 | while (*p) { |
1041 | parent = *p; | 1051 | parent = *p; |
@@ -1058,7 +1068,7 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc, | |||
1058 | rb_link_node(&new_ref->rb_node_node, parent, p); | 1068 | rb_link_node(&new_ref->rb_node_node, parent, p); |
1059 | rb_insert_color(&new_ref->rb_node_node, &proc->refs_by_node); | 1069 | rb_insert_color(&new_ref->rb_node_node, &proc->refs_by_node); |
1060 | 1070 | ||
1061 | new_ref->desc = (node == binder_context_mgr_node) ? 0 : 1; | 1071 | new_ref->desc = (node == context->binder_context_mgr_node) ? 0 : 1; |
1062 | for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) { | 1072 | for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) { |
1063 | ref = rb_entry(n, struct binder_ref, rb_node_desc); | 1073 | ref = rb_entry(n, struct binder_ref, rb_node_desc); |
1064 | if (ref->desc > new_ref->desc) | 1074 | if (ref->desc > new_ref->desc) |
@@ -1388,6 +1398,7 @@ static void binder_transaction(struct binder_proc *proc, | |||
1388 | struct binder_transaction *in_reply_to = NULL; | 1398 | struct binder_transaction *in_reply_to = NULL; |
1389 | struct binder_transaction_log_entry *e; | 1399 | struct binder_transaction_log_entry *e; |
1390 | uint32_t return_error; | 1400 | uint32_t return_error; |
1401 | struct binder_context *context = proc->context; | ||
1391 | 1402 | ||
1392 | e = binder_transaction_log_add(&binder_transaction_log); | 1403 | e = binder_transaction_log_add(&binder_transaction_log); |
1393 | e->call_type = reply ? 2 : !!(tr->flags & TF_ONE_WAY); | 1404 | e->call_type = reply ? 2 : !!(tr->flags & TF_ONE_WAY); |
@@ -1448,7 +1459,7 @@ static void binder_transaction(struct binder_proc *proc, | |||
1448 | } | 1459 | } |
1449 | target_node = ref->node; | 1460 | target_node = ref->node; |
1450 | } else { | 1461 | } else { |
1451 | target_node = binder_context_mgr_node; | 1462 | target_node = context->binder_context_mgr_node; |
1452 | if (target_node == NULL) { | 1463 | if (target_node == NULL) { |
1453 | return_error = BR_DEAD_REPLY; | 1464 | return_error = BR_DEAD_REPLY; |
1454 | goto err_no_context_mgr_node; | 1465 | goto err_no_context_mgr_node; |
@@ -1839,6 +1850,7 @@ static int binder_thread_write(struct binder_proc *proc, | |||
1839 | binder_size_t *consumed) | 1850 | binder_size_t *consumed) |
1840 | { | 1851 | { |
1841 | uint32_t cmd; | 1852 | uint32_t cmd; |
1853 | struct binder_context *context = proc->context; | ||
1842 | void __user *buffer = (void __user *)(uintptr_t)binder_buffer; | 1854 | void __user *buffer = (void __user *)(uintptr_t)binder_buffer; |
1843 | void __user *ptr = buffer + *consumed; | 1855 | void __user *ptr = buffer + *consumed; |
1844 | void __user *end = buffer + size; | 1856 | void __user *end = buffer + size; |
@@ -1865,10 +1877,10 @@ static int binder_thread_write(struct binder_proc *proc, | |||
1865 | if (get_user(target, (uint32_t __user *)ptr)) | 1877 | if (get_user(target, (uint32_t __user *)ptr)) |
1866 | return -EFAULT; | 1878 | return -EFAULT; |
1867 | ptr += sizeof(uint32_t); | 1879 | ptr += sizeof(uint32_t); |
1868 | if (target == 0 && binder_context_mgr_node && | 1880 | if (target == 0 && context->binder_context_mgr_node && |
1869 | (cmd == BC_INCREFS || cmd == BC_ACQUIRE)) { | 1881 | (cmd == BC_INCREFS || cmd == BC_ACQUIRE)) { |
1870 | ref = binder_get_ref_for_node(proc, | 1882 | ref = binder_get_ref_for_node(proc, |
1871 | binder_context_mgr_node); | 1883 | context->binder_context_mgr_node); |
1872 | if (ref->desc != target) { | 1884 | if (ref->desc != target) { |
1873 | binder_user_error("%d:%d tried to acquire reference to desc 0, got %d instead\n", | 1885 | binder_user_error("%d:%d tried to acquire reference to desc 0, got %d instead\n", |
1874 | proc->pid, thread->pid, | 1886 | proc->pid, thread->pid, |
@@ -2774,9 +2786,11 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp) | |||
2774 | { | 2786 | { |
2775 | int ret = 0; | 2787 | int ret = 0; |
2776 | struct binder_proc *proc = filp->private_data; | 2788 | struct binder_proc *proc = filp->private_data; |
2789 | struct binder_context *context = proc->context; | ||
2790 | |||
2777 | kuid_t curr_euid = current_euid(); | 2791 | kuid_t curr_euid = current_euid(); |
2778 | 2792 | ||
2779 | if (binder_context_mgr_node != NULL) { | 2793 | if (context->binder_context_mgr_node) { |
2780 | pr_err("BINDER_SET_CONTEXT_MGR already set\n"); | 2794 | pr_err("BINDER_SET_CONTEXT_MGR already set\n"); |
2781 | ret = -EBUSY; | 2795 | ret = -EBUSY; |
2782 | goto out; | 2796 | goto out; |
@@ -2784,27 +2798,27 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp) | |||
2784 | ret = security_binder_set_context_mgr(proc->tsk); | 2798 | ret = security_binder_set_context_mgr(proc->tsk); |
2785 | if (ret < 0) | 2799 | if (ret < 0) |
2786 | goto out; | 2800 | goto out; |
2787 | if (uid_valid(binder_context_mgr_uid)) { | 2801 | if (uid_valid(context->binder_context_mgr_uid)) { |
2788 | if (!uid_eq(binder_context_mgr_uid, curr_euid)) { | 2802 | if (!uid_eq(context->binder_context_mgr_uid, curr_euid)) { |
2789 | pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n", | 2803 | pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n", |
2790 | from_kuid(&init_user_ns, curr_euid), | 2804 | from_kuid(&init_user_ns, curr_euid), |
2791 | from_kuid(&init_user_ns, | 2805 | from_kuid(&init_user_ns, |
2792 | binder_context_mgr_uid)); | 2806 | context->binder_context_mgr_uid)); |
2793 | ret = -EPERM; | 2807 | ret = -EPERM; |
2794 | goto out; | 2808 | goto out; |
2795 | } | 2809 | } |
2796 | } else { | 2810 | } else { |
2797 | binder_context_mgr_uid = curr_euid; | 2811 | context->binder_context_mgr_uid = curr_euid; |
2798 | } | 2812 | } |
2799 | binder_context_mgr_node = binder_new_node(proc, 0, 0); | 2813 | context->binder_context_mgr_node = binder_new_node(proc, 0, 0); |
2800 | if (binder_context_mgr_node == NULL) { | 2814 | if (!context->binder_context_mgr_node) { |
2801 | ret = -ENOMEM; | 2815 | ret = -ENOMEM; |
2802 | goto out; | 2816 | goto out; |
2803 | } | 2817 | } |
2804 | binder_context_mgr_node->local_weak_refs++; | 2818 | context->binder_context_mgr_node->local_weak_refs++; |
2805 | binder_context_mgr_node->local_strong_refs++; | 2819 | context->binder_context_mgr_node->local_strong_refs++; |
2806 | binder_context_mgr_node->has_strong_ref = 1; | 2820 | context->binder_context_mgr_node->has_strong_ref = 1; |
2807 | binder_context_mgr_node->has_weak_ref = 1; | 2821 | context->binder_context_mgr_node->has_weak_ref = 1; |
2808 | out: | 2822 | out: |
2809 | return ret; | 2823 | return ret; |
2810 | } | 2824 | } |
@@ -3039,6 +3053,7 @@ static int binder_open(struct inode *nodp, struct file *filp) | |||
3039 | get_task_struct(current); | 3053 | get_task_struct(current); |
3040 | proc->tsk = current; | 3054 | proc->tsk = current; |
3041 | proc->vma_vm_mm = current->mm; | 3055 | proc->vma_vm_mm = current->mm; |
3056 | proc->context = &global_context; | ||
3042 | INIT_LIST_HEAD(&proc->todo); | 3057 | INIT_LIST_HEAD(&proc->todo); |
3043 | init_waitqueue_head(&proc->wait); | 3058 | init_waitqueue_head(&proc->wait); |
3044 | proc->default_priority = task_nice(current); | 3059 | proc->default_priority = task_nice(current); |
@@ -3151,6 +3166,7 @@ static int binder_node_release(struct binder_node *node, int refs) | |||
3151 | static void binder_deferred_release(struct binder_proc *proc) | 3166 | static void binder_deferred_release(struct binder_proc *proc) |
3152 | { | 3167 | { |
3153 | struct binder_transaction *t; | 3168 | struct binder_transaction *t; |
3169 | struct binder_context *context = proc->context; | ||
3154 | struct rb_node *n; | 3170 | struct rb_node *n; |
3155 | int threads, nodes, incoming_refs, outgoing_refs, buffers, | 3171 | int threads, nodes, incoming_refs, outgoing_refs, buffers, |
3156 | active_transactions, page_count; | 3172 | active_transactions, page_count; |
@@ -3160,11 +3176,12 @@ static void binder_deferred_release(struct binder_proc *proc) | |||
3160 | 3176 | ||
3161 | hlist_del(&proc->proc_node); | 3177 | hlist_del(&proc->proc_node); |
3162 | 3178 | ||
3163 | if (binder_context_mgr_node && binder_context_mgr_node->proc == proc) { | 3179 | if (context->binder_context_mgr_node && |
3180 | context->binder_context_mgr_node->proc == proc) { | ||
3164 | binder_debug(BINDER_DEBUG_DEAD_BINDER, | 3181 | binder_debug(BINDER_DEBUG_DEAD_BINDER, |
3165 | "%s: %d context_mgr_node gone\n", | 3182 | "%s: %d context_mgr_node gone\n", |
3166 | __func__, proc->pid); | 3183 | __func__, proc->pid); |
3167 | binder_context_mgr_node = NULL; | 3184 | context->binder_context_mgr_node = NULL; |
3168 | } | 3185 | } |
3169 | 3186 | ||
3170 | threads = 0; | 3187 | threads = 0; |