summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErwan Mahe <erwan.mahe@intel.com>2016-10-13 17:34:46 +0200
committerTasayco Loarte, VictorX <victorx.tasayco.loarte@intel.com>2016-10-19 09:54:53 +0100
commit42a125246bfb15762c41a9aa3f6358bd65ceb9f7 (patch)
treee204451da88d95b9b507a0d476f3e8489bb75cf5
parent7bf748c7ad9b46386b9ec03fbc9bcb87cdbca33c (diff)
downloadx86-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.c32
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,