| From 0a3ffab93fe52530602fe47cd74802cffdb19c05 Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= <arve@android.com> |
| Date: Mon, 24 Oct 2016 15:20:29 +0200 |
| Subject: ANDROID: binder: Add strong ref checks |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Arve Hjønnevåg <arve@android.com> |
| |
| 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> |
| |
| --- |
| drivers/android/binder.c | 30 +++++++++++++++++++++--------- |
| 1 file changed, 21 insertions(+), 9 deletions(-) |
| |
| --- a/drivers/android/binder.c |
| +++ b/drivers/android/binder.c |
| @@ -1003,7 +1003,7 @@ static int binder_dec_node(struct binder |
| |
| |
| 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 binder_ref *ref; |
| @@ -1011,12 +1011,16 @@ static struct binder_ref *binder_get_ref |
| while (n) { |
| ref = rb_entry(n, struct binder_ref, rb_node_desc); |
| |
| - if (desc < ref->desc) |
| + if (desc < ref->desc) { |
| n = n->rb_left; |
| - else if (desc > ref->desc) |
| + } else if (desc > ref->desc) { |
| 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 NULL; |
| } |
| @@ -1286,7 +1290,10 @@ static void binder_transaction_buffer_re |
| } break; |
| case BINDER_TYPE_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) { |
| pr_err("transaction release %d bad handle %d\n", |
| @@ -1381,7 +1388,7 @@ static void binder_transaction(struct bi |
| if (tr->target.handle) { |
| struct binder_ref *ref; |
| |
| - ref = binder_get_ref(proc, tr->target.handle); |
| + ref = binder_get_ref(proc, tr->target.handle, true); |
| if (ref == NULL) { |
| binder_user_error("%d:%d got transaction to invalid handle\n", |
| proc->pid, thread->pid); |
| @@ -1590,7 +1597,10 @@ static void binder_transaction(struct bi |
| } break; |
| case BINDER_TYPE_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) { |
| binder_user_error("%d:%d got transaction with invalid handle, %d\n", |
| @@ -1801,7 +1811,9 @@ static int binder_thread_write(struct bi |
| ref->desc); |
| } |
| } else |
| - ref = binder_get_ref(proc, target); |
| + ref = binder_get_ref(proc, target, |
| + cmd == BC_ACQUIRE || |
| + cmd == BC_RELEASE); |
| if (ref == NULL) { |
| binder_user_error("%d:%d refcount change on invalid ref %d\n", |
| proc->pid, thread->pid, target); |
| @@ -1997,7 +2009,7 @@ static int binder_thread_write(struct bi |
| if (get_user(cookie, (binder_uintptr_t __user *)ptr)) |
| return -EFAULT; |
| ptr += sizeof(binder_uintptr_t); |
| - ref = binder_get_ref(proc, target); |
| + ref = binder_get_ref(proc, target, false); |
| if (ref == NULL) { |
| binder_user_error("%d:%d %s invalid ref %d\n", |
| proc->pid, thread->pid, |