Commit 342e5c90 authored by Martijn Coenen's avatar Martijn Coenen Committed by Greg Kroah-Hartman

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: default avatarMartijn Coenen <maco@google.com>
[jstultz: Minor checkpatch fix]
Signed-off-by: default avatarJohn Stultz <john.stultz@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent feba3900
...@@ -56,8 +56,6 @@ static HLIST_HEAD(binder_dead_nodes); ...@@ -56,8 +56,6 @@ static HLIST_HEAD(binder_dead_nodes);
static struct dentry *binder_debugfs_dir_entry_root; static struct dentry *binder_debugfs_dir_entry_root;
static struct dentry *binder_debugfs_dir_entry_proc; static struct dentry *binder_debugfs_dir_entry_proc;
static struct binder_node *binder_context_mgr_node;
static kuid_t binder_context_mgr_uid = INVALID_UID;
static int binder_last_id; static int binder_last_id;
#define BINDER_DEBUG_ENTRY(name) \ #define BINDER_DEBUG_ENTRY(name) \
...@@ -215,6 +213,15 @@ static struct binder_transaction_log_entry *binder_transaction_log_add( ...@@ -215,6 +213,15 @@ static struct binder_transaction_log_entry *binder_transaction_log_add(
return e; return e;
} }
struct binder_context {
struct binder_node *binder_context_mgr_node;
kuid_t binder_context_mgr_uid;
};
static struct binder_context global_context = {
.binder_context_mgr_uid = INVALID_UID,
};
struct binder_work { struct binder_work {
struct list_head entry; struct list_head entry;
enum { enum {
...@@ -330,6 +337,7 @@ struct binder_proc { ...@@ -330,6 +337,7 @@ struct binder_proc {
int ready_threads; int ready_threads;
long default_priority; long default_priority;
struct dentry *debugfs_entry; struct dentry *debugfs_entry;
struct binder_context *context;
}; };
enum { enum {
...@@ -934,8 +942,9 @@ static int binder_inc_node(struct binder_node *node, int strong, int internal, ...@@ -934,8 +942,9 @@ static int binder_inc_node(struct binder_node *node, int strong, int internal,
if (internal) { if (internal) {
if (target_list == NULL && if (target_list == NULL &&
node->internal_strong_refs == 0 && node->internal_strong_refs == 0 &&
!(node == binder_context_mgr_node && !(node->proc &&
node->has_strong_ref)) { node == node->proc->context->binder_context_mgr_node &&
node->has_strong_ref)) {
pr_err("invalid inc strong node for %d\n", pr_err("invalid inc strong node for %d\n",
node->debug_id); node->debug_id);
return -EINVAL; return -EINVAL;
...@@ -1036,6 +1045,7 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc, ...@@ -1036,6 +1045,7 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc,
struct rb_node **p = &proc->refs_by_node.rb_node; struct rb_node **p = &proc->refs_by_node.rb_node;
struct rb_node *parent = NULL; struct rb_node *parent = NULL;
struct binder_ref *ref, *new_ref; struct binder_ref *ref, *new_ref;
struct binder_context *context = proc->context;
while (*p) { while (*p) {
parent = *p; parent = *p;
...@@ -1058,7 +1068,7 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc, ...@@ -1058,7 +1068,7 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc,
rb_link_node(&new_ref->rb_node_node, parent, p); rb_link_node(&new_ref->rb_node_node, parent, p);
rb_insert_color(&new_ref->rb_node_node, &proc->refs_by_node); rb_insert_color(&new_ref->rb_node_node, &proc->refs_by_node);
new_ref->desc = (node == binder_context_mgr_node) ? 0 : 1; new_ref->desc = (node == context->binder_context_mgr_node) ? 0 : 1;
for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) { for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) {
ref = rb_entry(n, struct binder_ref, rb_node_desc); ref = rb_entry(n, struct binder_ref, rb_node_desc);
if (ref->desc > new_ref->desc) if (ref->desc > new_ref->desc)
...@@ -1388,6 +1398,7 @@ static void binder_transaction(struct binder_proc *proc, ...@@ -1388,6 +1398,7 @@ static void binder_transaction(struct binder_proc *proc,
struct binder_transaction *in_reply_to = NULL; struct binder_transaction *in_reply_to = NULL;
struct binder_transaction_log_entry *e; struct binder_transaction_log_entry *e;
uint32_t return_error; uint32_t return_error;
struct binder_context *context = proc->context;
e = binder_transaction_log_add(&binder_transaction_log); e = binder_transaction_log_add(&binder_transaction_log);
e->call_type = reply ? 2 : !!(tr->flags & TF_ONE_WAY); e->call_type = reply ? 2 : !!(tr->flags & TF_ONE_WAY);
...@@ -1448,7 +1459,7 @@ static void binder_transaction(struct binder_proc *proc, ...@@ -1448,7 +1459,7 @@ static void binder_transaction(struct binder_proc *proc,
} }
target_node = ref->node; target_node = ref->node;
} else { } else {
target_node = binder_context_mgr_node; target_node = context->binder_context_mgr_node;
if (target_node == NULL) { if (target_node == NULL) {
return_error = BR_DEAD_REPLY; return_error = BR_DEAD_REPLY;
goto err_no_context_mgr_node; goto err_no_context_mgr_node;
...@@ -1839,6 +1850,7 @@ static int binder_thread_write(struct binder_proc *proc, ...@@ -1839,6 +1850,7 @@ static int binder_thread_write(struct binder_proc *proc,
binder_size_t *consumed) binder_size_t *consumed)
{ {
uint32_t cmd; uint32_t cmd;
struct binder_context *context = proc->context;
void __user *buffer = (void __user *)(uintptr_t)binder_buffer; void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
void __user *ptr = buffer + *consumed; void __user *ptr = buffer + *consumed;
void __user *end = buffer + size; void __user *end = buffer + size;
...@@ -1865,10 +1877,10 @@ static int binder_thread_write(struct binder_proc *proc, ...@@ -1865,10 +1877,10 @@ static int binder_thread_write(struct binder_proc *proc,
if (get_user(target, (uint32_t __user *)ptr)) if (get_user(target, (uint32_t __user *)ptr))
return -EFAULT; return -EFAULT;
ptr += sizeof(uint32_t); ptr += sizeof(uint32_t);
if (target == 0 && binder_context_mgr_node && if (target == 0 && context->binder_context_mgr_node &&
(cmd == BC_INCREFS || cmd == BC_ACQUIRE)) { (cmd == BC_INCREFS || cmd == BC_ACQUIRE)) {
ref = binder_get_ref_for_node(proc, ref = binder_get_ref_for_node(proc,
binder_context_mgr_node); context->binder_context_mgr_node);
if (ref->desc != target) { if (ref->desc != target) {
binder_user_error("%d:%d tried to acquire reference to desc 0, got %d instead\n", binder_user_error("%d:%d tried to acquire reference to desc 0, got %d instead\n",
proc->pid, thread->pid, proc->pid, thread->pid,
...@@ -2774,9 +2786,11 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp) ...@@ -2774,9 +2786,11 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp)
{ {
int ret = 0; int ret = 0;
struct binder_proc *proc = filp->private_data; struct binder_proc *proc = filp->private_data;
struct binder_context *context = proc->context;
kuid_t curr_euid = current_euid(); kuid_t curr_euid = current_euid();
if (binder_context_mgr_node != NULL) { if (context->binder_context_mgr_node) {
pr_err("BINDER_SET_CONTEXT_MGR already set\n"); pr_err("BINDER_SET_CONTEXT_MGR already set\n");
ret = -EBUSY; ret = -EBUSY;
goto out; goto out;
...@@ -2784,27 +2798,27 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp) ...@@ -2784,27 +2798,27 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp)
ret = security_binder_set_context_mgr(proc->tsk); ret = security_binder_set_context_mgr(proc->tsk);
if (ret < 0) if (ret < 0)
goto out; goto out;
if (uid_valid(binder_context_mgr_uid)) { if (uid_valid(context->binder_context_mgr_uid)) {
if (!uid_eq(binder_context_mgr_uid, curr_euid)) { if (!uid_eq(context->binder_context_mgr_uid, curr_euid)) {
pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n", pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n",
from_kuid(&init_user_ns, curr_euid), from_kuid(&init_user_ns, curr_euid),
from_kuid(&init_user_ns, from_kuid(&init_user_ns,
binder_context_mgr_uid)); context->binder_context_mgr_uid));
ret = -EPERM; ret = -EPERM;
goto out; goto out;
} }
} else { } else {
binder_context_mgr_uid = curr_euid; context->binder_context_mgr_uid = curr_euid;
} }
binder_context_mgr_node = binder_new_node(proc, 0, 0); context->binder_context_mgr_node = binder_new_node(proc, 0, 0);
if (binder_context_mgr_node == NULL) { if (!context->binder_context_mgr_node) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
binder_context_mgr_node->local_weak_refs++; context->binder_context_mgr_node->local_weak_refs++;
binder_context_mgr_node->local_strong_refs++; context->binder_context_mgr_node->local_strong_refs++;
binder_context_mgr_node->has_strong_ref = 1; context->binder_context_mgr_node->has_strong_ref = 1;
binder_context_mgr_node->has_weak_ref = 1; context->binder_context_mgr_node->has_weak_ref = 1;
out: out:
return ret; return ret;
} }
...@@ -3039,6 +3053,7 @@ static int binder_open(struct inode *nodp, struct file *filp) ...@@ -3039,6 +3053,7 @@ static int binder_open(struct inode *nodp, struct file *filp)
get_task_struct(current); get_task_struct(current);
proc->tsk = current; proc->tsk = current;
proc->vma_vm_mm = current->mm; proc->vma_vm_mm = current->mm;
proc->context = &global_context;
INIT_LIST_HEAD(&proc->todo); INIT_LIST_HEAD(&proc->todo);
init_waitqueue_head(&proc->wait); init_waitqueue_head(&proc->wait);
proc->default_priority = task_nice(current); proc->default_priority = task_nice(current);
...@@ -3151,6 +3166,7 @@ static int binder_node_release(struct binder_node *node, int refs) ...@@ -3151,6 +3166,7 @@ static int binder_node_release(struct binder_node *node, int refs)
static void binder_deferred_release(struct binder_proc *proc) static void binder_deferred_release(struct binder_proc *proc)
{ {
struct binder_transaction *t; struct binder_transaction *t;
struct binder_context *context = proc->context;
struct rb_node *n; struct rb_node *n;
int threads, nodes, incoming_refs, outgoing_refs, buffers, int threads, nodes, incoming_refs, outgoing_refs, buffers,
active_transactions, page_count; active_transactions, page_count;
...@@ -3160,11 +3176,12 @@ static void binder_deferred_release(struct binder_proc *proc) ...@@ -3160,11 +3176,12 @@ static void binder_deferred_release(struct binder_proc *proc)
hlist_del(&proc->proc_node); hlist_del(&proc->proc_node);
if (binder_context_mgr_node && binder_context_mgr_node->proc == proc) { if (context->binder_context_mgr_node &&
context->binder_context_mgr_node->proc == proc) {
binder_debug(BINDER_DEBUG_DEAD_BINDER, binder_debug(BINDER_DEBUG_DEAD_BINDER,
"%s: %d context_mgr_node gone\n", "%s: %d context_mgr_node gone\n",
__func__, proc->pid); __func__, proc->pid);
binder_context_mgr_node = NULL; context->binder_context_mgr_node = NULL;
} }
threads = 0; threads = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment