Commit 0a3ffab93fe52530602fe47cd74802cffdb19c05
Committed by
Greg Kroah-Hartman
1 parent
07d9a38068
ANDROID: binder: Add strong ref checks
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> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Showing 1 changed file with 21 additions and 9 deletions Side-by-side Diff
drivers/android/binder.c
... | ... | @@ -1002,7 +1002,7 @@ |
1002 | 1002 | |
1003 | 1003 | |
1004 | 1004 | static struct binder_ref *binder_get_ref(struct binder_proc *proc, |
1005 | - uint32_t desc) | |
1005 | + u32 desc, bool need_strong_ref) | |
1006 | 1006 | { |
1007 | 1007 | struct rb_node *n = proc->refs_by_desc.rb_node; |
1008 | 1008 | struct binder_ref *ref; |
1009 | 1009 | |
1010 | 1010 | |
1011 | 1011 | |
... | ... | @@ -1010,12 +1010,16 @@ |
1010 | 1010 | while (n) { |
1011 | 1011 | ref = rb_entry(n, struct binder_ref, rb_node_desc); |
1012 | 1012 | |
1013 | - if (desc < ref->desc) | |
1013 | + if (desc < ref->desc) { | |
1014 | 1014 | n = n->rb_left; |
1015 | - else if (desc > ref->desc) | |
1015 | + } else if (desc > ref->desc) { | |
1016 | 1016 | n = n->rb_right; |
1017 | - else | |
1017 | + } else if (need_strong_ref && !ref->strong) { | |
1018 | + binder_user_error("tried to use weak ref as strong ref\n"); | |
1019 | + return NULL; | |
1020 | + } else { | |
1018 | 1021 | return ref; |
1022 | + } | |
1019 | 1023 | } |
1020 | 1024 | return NULL; |
1021 | 1025 | } |
1022 | 1026 | |
... | ... | @@ -1285,8 +1289,11 @@ |
1285 | 1289 | } break; |
1286 | 1290 | case BINDER_TYPE_HANDLE: |
1287 | 1291 | case BINDER_TYPE_WEAK_HANDLE: { |
1288 | - struct binder_ref *ref = binder_get_ref(proc, fp->handle); | |
1292 | + struct binder_ref *ref; | |
1289 | 1293 | |
1294 | + ref = binder_get_ref(proc, fp->handle, | |
1295 | + fp->type == BINDER_TYPE_HANDLE); | |
1296 | + | |
1290 | 1297 | if (ref == NULL) { |
1291 | 1298 | pr_err("transaction release %d bad handle %d\n", |
1292 | 1299 | debug_id, fp->handle); |
... | ... | @@ -1380,7 +1387,7 @@ |
1380 | 1387 | if (tr->target.handle) { |
1381 | 1388 | struct binder_ref *ref; |
1382 | 1389 | |
1383 | - ref = binder_get_ref(proc, tr->target.handle); | |
1390 | + ref = binder_get_ref(proc, tr->target.handle, true); | |
1384 | 1391 | if (ref == NULL) { |
1385 | 1392 | binder_user_error("%d:%d got transaction to invalid handle\n", |
1386 | 1393 | proc->pid, thread->pid); |
1387 | 1394 | |
... | ... | @@ -1589,8 +1596,11 @@ |
1589 | 1596 | } break; |
1590 | 1597 | case BINDER_TYPE_HANDLE: |
1591 | 1598 | case BINDER_TYPE_WEAK_HANDLE: { |
1592 | - struct binder_ref *ref = binder_get_ref(proc, fp->handle); | |
1599 | + struct binder_ref *ref; | |
1593 | 1600 | |
1601 | + ref = binder_get_ref(proc, fp->handle, | |
1602 | + fp->type == BINDER_TYPE_HANDLE); | |
1603 | + | |
1594 | 1604 | if (ref == NULL) { |
1595 | 1605 | binder_user_error("%d:%d got transaction with invalid handle, %d\n", |
1596 | 1606 | proc->pid, |
... | ... | @@ -1800,7 +1810,9 @@ |
1800 | 1810 | ref->desc); |
1801 | 1811 | } |
1802 | 1812 | } else |
1803 | - ref = binder_get_ref(proc, target); | |
1813 | + ref = binder_get_ref(proc, target, | |
1814 | + cmd == BC_ACQUIRE || | |
1815 | + cmd == BC_RELEASE); | |
1804 | 1816 | if (ref == NULL) { |
1805 | 1817 | binder_user_error("%d:%d refcount change on invalid ref %d\n", |
1806 | 1818 | proc->pid, thread->pid, target); |
... | ... | @@ -1996,7 +2008,7 @@ |
1996 | 2008 | if (get_user(cookie, (binder_uintptr_t __user *)ptr)) |
1997 | 2009 | return -EFAULT; |
1998 | 2010 | ptr += sizeof(binder_uintptr_t); |
1999 | - ref = binder_get_ref(proc, target); | |
2011 | + ref = binder_get_ref(proc, target, false); | |
2000 | 2012 | if (ref == NULL) { |
2001 | 2013 | binder_user_error("%d:%d %s invalid ref %d\n", |
2002 | 2014 | proc->pid, thread->pid, |