Commit 9a6d0e76 authored by Arve Hjønnevåg's avatar Arve Hjønnevåg Committed by Luis Henriques

ANDROID: binder: Add strong ref checks

BugLink: http://bugs.launchpad.net/bugs/1642572

commit 0a3ffab9 upstream.

Prevent using a binder_ref with only weak references where a strong
reference is required.
Signed-off-by: default avatarArve Hjønnevåg <arve@android.com>
Signed-off-by: default avatarMartijn Coenen <maco@android.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarLuis Henriques <luis.henriques@canonical.com>
parent 3fa6890e
...@@ -1003,7 +1003,7 @@ static int binder_dec_node(struct binder_node *node, int strong, int internal) ...@@ -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,13 +1011,17 @@ static struct binder_ref *binder_get_ref(struct binder_proc *proc, ...@@ -1011,13 +1011,17 @@ 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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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,
......
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