ANDROID: binder: Add strong ref checks
commit 0a3ffab93fe52530602fe47cd74802cffdb19c05 upstream. Prevent using a binder_ref with only weak references where a strong reference is required. Signed-off-by: Arve Hjønnevåg <arve@android.com> Signed-off-by: Martijn Coenen <maco@android.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
c5be1e1314
commit
14f09e8e7c
1 changed files with 21 additions and 9 deletions
|
@ -1003,7 +1003,7 @@ static int binder_dec_node(struct binder_node *node, int strong, int internal)
|
||||||
|
|
||||||
|
|
||||||
static struct binder_ref *binder_get_ref(struct binder_proc *proc,
|
static struct binder_ref *binder_get_ref(struct binder_proc *proc,
|
||||||
uint32_t desc)
|
u32 desc, bool need_strong_ref)
|
||||||
{
|
{
|
||||||
struct rb_node *n = proc->refs_by_desc.rb_node;
|
struct rb_node *n = proc->refs_by_desc.rb_node;
|
||||||
struct binder_ref *ref;
|
struct binder_ref *ref;
|
||||||
|
@ -1011,12 +1011,16 @@ static struct binder_ref *binder_get_ref(struct binder_proc *proc,
|
||||||
while (n) {
|
while (n) {
|
||||||
ref = rb_entry(n, struct binder_ref, rb_node_desc);
|
ref = rb_entry(n, struct binder_ref, rb_node_desc);
|
||||||
|
|
||||||
if (desc < ref->desc)
|
if (desc < ref->desc) {
|
||||||
n = n->rb_left;
|
n = n->rb_left;
|
||||||
else if (desc > ref->desc)
|
} else if (desc > ref->desc) {
|
||||||
n = n->rb_right;
|
n = n->rb_right;
|
||||||
else
|
} else if (need_strong_ref && !ref->strong) {
|
||||||
|
binder_user_error("tried to use weak ref as strong ref\n");
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
return ref;
|
return ref;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1286,7 +1290,10 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
|
||||||
} break;
|
} break;
|
||||||
case BINDER_TYPE_HANDLE:
|
case BINDER_TYPE_HANDLE:
|
||||||
case BINDER_TYPE_WEAK_HANDLE: {
|
case BINDER_TYPE_WEAK_HANDLE: {
|
||||||
struct binder_ref *ref = binder_get_ref(proc, fp->handle);
|
struct binder_ref *ref;
|
||||||
|
|
||||||
|
ref = binder_get_ref(proc, fp->handle,
|
||||||
|
fp->type == BINDER_TYPE_HANDLE);
|
||||||
|
|
||||||
if (ref == NULL) {
|
if (ref == NULL) {
|
||||||
pr_err("transaction release %d bad handle %d\n",
|
pr_err("transaction release %d bad handle %d\n",
|
||||||
|
@ -1380,7 +1387,7 @@ static void binder_transaction(struct binder_proc *proc,
|
||||||
if (tr->target.handle) {
|
if (tr->target.handle) {
|
||||||
struct binder_ref *ref;
|
struct binder_ref *ref;
|
||||||
|
|
||||||
ref = binder_get_ref(proc, tr->target.handle);
|
ref = binder_get_ref(proc, tr->target.handle, true);
|
||||||
if (ref == NULL) {
|
if (ref == NULL) {
|
||||||
binder_user_error("%d:%d got transaction to invalid handle\n",
|
binder_user_error("%d:%d got transaction to invalid handle\n",
|
||||||
proc->pid, thread->pid);
|
proc->pid, thread->pid);
|
||||||
|
@ -1583,7 +1590,10 @@ static void binder_transaction(struct binder_proc *proc,
|
||||||
} break;
|
} break;
|
||||||
case BINDER_TYPE_HANDLE:
|
case BINDER_TYPE_HANDLE:
|
||||||
case BINDER_TYPE_WEAK_HANDLE: {
|
case BINDER_TYPE_WEAK_HANDLE: {
|
||||||
struct binder_ref *ref = binder_get_ref(proc, fp->handle);
|
struct binder_ref *ref;
|
||||||
|
|
||||||
|
ref = binder_get_ref(proc, fp->handle,
|
||||||
|
fp->type == BINDER_TYPE_HANDLE);
|
||||||
|
|
||||||
if (ref == NULL) {
|
if (ref == NULL) {
|
||||||
binder_user_error("%d:%d got transaction with invalid handle, %d\n",
|
binder_user_error("%d:%d got transaction with invalid handle, %d\n",
|
||||||
|
@ -1794,7 +1804,9 @@ static int binder_thread_write(struct binder_proc *proc,
|
||||||
ref->desc);
|
ref->desc);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
ref = binder_get_ref(proc, target);
|
ref = binder_get_ref(proc, target,
|
||||||
|
cmd == BC_ACQUIRE ||
|
||||||
|
cmd == BC_RELEASE);
|
||||||
if (ref == NULL) {
|
if (ref == NULL) {
|
||||||
binder_user_error("%d:%d refcount change on invalid ref %d\n",
|
binder_user_error("%d:%d refcount change on invalid ref %d\n",
|
||||||
proc->pid, thread->pid, target);
|
proc->pid, thread->pid, target);
|
||||||
|
@ -1990,7 +2002,7 @@ static int binder_thread_write(struct binder_proc *proc,
|
||||||
if (get_user(cookie, (binder_uintptr_t __user *)ptr))
|
if (get_user(cookie, (binder_uintptr_t __user *)ptr))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ptr += sizeof(binder_uintptr_t);
|
ptr += sizeof(binder_uintptr_t);
|
||||||
ref = binder_get_ref(proc, target);
|
ref = binder_get_ref(proc, target, false);
|
||||||
if (ref == NULL) {
|
if (ref == NULL) {
|
||||||
binder_user_error("%d:%d %s invalid ref %d\n",
|
binder_user_error("%d:%d %s invalid ref %d\n",
|
||||||
proc->pid, thread->pid,
|
proc->pid, thread->pid,
|
||||||
|
|
Loading…
Add table
Reference in a new issue