diff options
author | Erwan Mahe <erwan.mahe@intel.com> | 2016-10-13 17:34:46 +0200 |
---|---|---|
committer | Tasayco Loarte, VictorX <victorx.tasayco.loarte@intel.com> | 2016-10-19 09:54:53 +0100 |
commit | 42a125246bfb15762c41a9aa3f6358bd65ceb9f7 (patch) | |
tree | e204451da88d95b9b507a0d476f3e8489bb75cf5 | |
parent | 7bf748c7ad9b46386b9ec03fbc9bcb87cdbca33c (diff) | |
download | x86-42a125246bfb15762c41a9aa3f6358bd65ceb9f7.tar.gz |
ANDROID: binder: Add strong ref checks
CVE-2016-6674
Prevent using a binder_ref with only weak references where a strong
reference is required.
BUG: 30445380
Change-Id: I39a39e2f9cb80a603fc98f7c4af9230ff2b884b2
Tracked-On: https://jira01.devtools.intel.com/browse/AW-2263
Signed-off-by: Arve Hjønnevåg <arve@android.com>
Signed-off-by: Erwan Mahe <erwan.mahe@intel.com>
Reviewed-on: https://android.intel.com/545351
Reviewed-by: Dubray, SimonX <simonx.dubray@intel.com>
Reviewed-by: Tasayco Loarte, VictorX <victorx.tasayco.loarte@intel.com>
Reviewed-by: Maalem, Saadi <saadi.maalem@intel.com>
-rw-r--r-- | drivers/android/binder.c | 32 |
1 files changed, 20 insertions, 12 deletions
diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 8c29051d5119..f5e93a751a36 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -1004,7 +1004,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, - uint32_t desc) + uint32_t desc, bool need_strong_ref) { struct rb_node *n = proc->refs_by_desc.rb_node; struct binder_ref *ref; @@ -1012,12 +1012,16 @@ static struct binder_ref *binder_get_ref(struct binder_proc *proc, while (n) { ref = rb_entry(n, struct binder_ref, rb_node_desc); - if (desc < ref->desc) - n = n->rb_left; - else if (desc > ref->desc) - n = n->rb_right; - else - return ref; + if (desc < ref->desc) { + n = n->rb_left; + } else if (desc > ref->desc) { + n = n->rb_right; + } 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; } @@ -1287,7 +1291,8 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, } break; case BINDER_TYPE_HANDLE: case BINDER_TYPE_WEAK_HANDLE: { - struct binder_ref *ref = binder_get_ref(proc, fp->handle); + struct binder_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", @@ -1382,7 +1387,7 @@ static void binder_transaction(struct binder_proc *proc, 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); @@ -1589,7 +1594,8 @@ static void binder_transaction(struct binder_proc *proc, } break; case BINDER_TYPE_HANDLE: case BINDER_TYPE_WEAK_HANDLE: { - struct binder_ref *ref = binder_get_ref(proc, fp->handle); + struct binder_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", @@ -1797,7 +1803,9 @@ static int binder_thread_write(struct binder_proc *proc, 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); @@ -1993,7 +2001,7 @@ static int binder_thread_write(struct binder_proc *proc, 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, |