aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/android/binder.c
diff options
context:
space:
mode:
authorTodd Kjos <tkjos@android.com>2017-06-29 15:01:59 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-07-17 08:48:23 -0400
commitadc1884222276df6eb018f78bccacbcd78a0b9f6 (patch)
tree3b041b13a03729009bd2fa063fc2163bc27aac0f /drivers/android/binder.c
parent372e3147df7016ebeaa372939e8774a1292db558 (diff)
binder: use node->tmp_refs to ensure node safety
When obtaining a node via binder_get_node(), binder_get_node_from_ref() or binder_new_node(), increment node->tmp_refs to take a temporary reference on the node to ensure the node persists while being used. binder_put_node() must be called to remove the temporary reference. Signed-off-by: Todd Kjos <tkjos@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/android/binder.c')
-rw-r--r--drivers/android/binder.c124
1 files changed, 104 insertions, 20 deletions
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 4d0b99862339..ec050c6d1192 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -274,6 +274,7 @@ struct binder_node {
274 int internal_strong_refs; 274 int internal_strong_refs;
275 int local_weak_refs; 275 int local_weak_refs;
276 int local_strong_refs; 276 int local_strong_refs;
277 int tmp_refs;
277 binder_uintptr_t ptr; 278 binder_uintptr_t ptr;
278 binder_uintptr_t cookie; 279 binder_uintptr_t cookie;
279 unsigned has_strong_ref:1; 280 unsigned has_strong_ref:1;
@@ -427,6 +428,7 @@ static void
427binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer); 428binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer);
428static void binder_free_thread(struct binder_thread *thread); 429static void binder_free_thread(struct binder_thread *thread);
429static void binder_free_proc(struct binder_proc *proc); 430static void binder_free_proc(struct binder_proc *proc);
431static void binder_inc_node_tmpref(struct binder_node *node);
430 432
431static int task_get_unused_fd_flags(struct binder_proc *proc, int flags) 433static int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
432{ 434{
@@ -521,8 +523,15 @@ static struct binder_node *binder_get_node(struct binder_proc *proc,
521 n = n->rb_left; 523 n = n->rb_left;
522 else if (ptr > node->ptr) 524 else if (ptr > node->ptr)
523 n = n->rb_right; 525 n = n->rb_right;
524 else 526 else {
527 /*
528 * take an implicit weak reference
529 * to ensure node stays alive until
530 * call to binder_put_node()
531 */
532 binder_inc_node_tmpref(node);
525 return node; 533 return node;
534 }
526 } 535 }
527 return NULL; 536 return NULL;
528} 537}
@@ -551,6 +560,7 @@ static struct binder_node *binder_new_node(struct binder_proc *proc,
551 if (node == NULL) 560 if (node == NULL)
552 return NULL; 561 return NULL;
553 binder_stats_created(BINDER_STAT_NODE); 562 binder_stats_created(BINDER_STAT_NODE);
563 node->tmp_refs++;
554 rb_link_node(&node->rb_node, parent, p); 564 rb_link_node(&node->rb_node, parent, p);
555 rb_insert_color(&node->rb_node, &proc->nodes); 565 rb_insert_color(&node->rb_node, &proc->nodes);
556 node->debug_id = atomic_inc_return(&binder_last_id); 566 node->debug_id = atomic_inc_return(&binder_last_id);
@@ -615,7 +625,8 @@ static int binder_dec_node(struct binder_node *node, int strong, int internal)
615 } else { 625 } else {
616 if (!internal) 626 if (!internal)
617 node->local_weak_refs--; 627 node->local_weak_refs--;
618 if (node->local_weak_refs || !hlist_empty(&node->refs)) 628 if (node->local_weak_refs || node->tmp_refs ||
629 !hlist_empty(&node->refs))
619 return 0; 630 return 0;
620 } 631 }
621 if (node->proc && (node->has_strong_ref || node->has_weak_ref)) { 632 if (node->proc && (node->has_strong_ref || node->has_weak_ref)) {
@@ -625,7 +636,7 @@ static int binder_dec_node(struct binder_node *node, int strong, int internal)
625 } 636 }
626 } else { 637 } else {
627 if (hlist_empty(&node->refs) && !node->local_strong_refs && 638 if (hlist_empty(&node->refs) && !node->local_strong_refs &&
628 !node->local_weak_refs) { 639 !node->local_weak_refs && !node->tmp_refs) {
629 list_del_init(&node->work.entry); 640 list_del_init(&node->work.entry);
630 if (node->proc) { 641 if (node->proc) {
631 rb_erase(&node->rb_node, &node->proc->nodes); 642 rb_erase(&node->rb_node, &node->proc->nodes);
@@ -648,6 +659,46 @@ static int binder_dec_node(struct binder_node *node, int strong, int internal)
648 return 0; 659 return 0;
649} 660}
650 661
662/**
663 * binder_inc_node_tmpref() - take a temporary reference on node
664 * @node: node to reference
665 *
666 * Take reference on node to prevent the node from being freed
667 * while referenced only by a local variable
668 */
669static void binder_inc_node_tmpref(struct binder_node *node)
670{
671 /*
672 * No call to binder_inc_node() is needed since we
673 * don't need to inform userspace of any changes to
674 * tmp_refs
675 */
676 node->tmp_refs++;
677}
678
679/**
680 * binder_dec_node_tmpref() - remove a temporary reference on node
681 * @node: node to reference
682 *
683 * Release temporary reference on node taken via binder_inc_node_tmpref()
684 */
685static void binder_dec_node_tmpref(struct binder_node *node)
686{
687 node->tmp_refs--;
688 BUG_ON(node->tmp_refs < 0);
689 /*
690 * Call binder_dec_node() to check if all refcounts are 0
691 * and cleanup is needed. Calling with strong=0 and internal=1
692 * causes no actual reference to be released in binder_dec_node().
693 * If that changes, a change is needed here too.
694 */
695 binder_dec_node(node, 0, 1);
696}
697
698static void binder_put_node(struct binder_node *node)
699{
700 binder_dec_node_tmpref(node);
701}
651 702
652static struct binder_ref *binder_get_ref(struct binder_proc *proc, 703static struct binder_ref *binder_get_ref(struct binder_proc *proc,
653 u32 desc, bool need_strong_ref) 704 u32 desc, bool need_strong_ref)
@@ -888,6 +939,11 @@ static struct binder_node *binder_get_node_from_ref(
888 if (!ref) 939 if (!ref)
889 goto err_no_ref; 940 goto err_no_ref;
890 node = ref->node; 941 node = ref->node;
942 /*
943 * Take an implicit reference on the node to ensure
944 * it stays alive until the call to binder_put_node()
945 */
946 binder_inc_node_tmpref(node);
891 if (rdata) 947 if (rdata)
892 *rdata = ref->data; 948 *rdata = ref->data;
893 949
@@ -1348,6 +1404,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
1348 node->debug_id, (u64)node->ptr); 1404 node->debug_id, (u64)node->ptr);
1349 binder_dec_node(node, hdr->type == BINDER_TYPE_BINDER, 1405 binder_dec_node(node, hdr->type == BINDER_TYPE_BINDER,
1350 0); 1406 0);
1407 binder_put_node(node);
1351 } break; 1408 } break;
1352 case BINDER_TYPE_HANDLE: 1409 case BINDER_TYPE_HANDLE:
1353 case BINDER_TYPE_WEAK_HANDLE: { 1410 case BINDER_TYPE_WEAK_HANDLE: {
@@ -1441,7 +1498,7 @@ static int binder_translate_binder(struct flat_binder_object *fp,
1441 struct binder_proc *proc = thread->proc; 1498 struct binder_proc *proc = thread->proc;
1442 struct binder_proc *target_proc = t->to_proc; 1499 struct binder_proc *target_proc = t->to_proc;
1443 struct binder_ref_data rdata; 1500 struct binder_ref_data rdata;
1444 int ret; 1501 int ret = 0;
1445 1502
1446 node = binder_get_node(proc, fp->binder); 1503 node = binder_get_node(proc, fp->binder);
1447 if (!node) { 1504 if (!node) {
@@ -1457,16 +1514,19 @@ static int binder_translate_binder(struct flat_binder_object *fp,
1457 proc->pid, thread->pid, (u64)fp->binder, 1514 proc->pid, thread->pid, (u64)fp->binder,
1458 node->debug_id, (u64)fp->cookie, 1515 node->debug_id, (u64)fp->cookie,
1459 (u64)node->cookie); 1516 (u64)node->cookie);
1460 return -EINVAL; 1517 ret = -EINVAL;
1518 goto done;
1519 }
1520 if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) {
1521 ret = -EPERM;
1522 goto done;
1461 } 1523 }
1462 if (security_binder_transfer_binder(proc->tsk, target_proc->tsk))
1463 return -EPERM;
1464 1524
1465 ret = binder_inc_ref_for_node(target_proc, node, 1525 ret = binder_inc_ref_for_node(target_proc, node,
1466 fp->hdr.type == BINDER_TYPE_BINDER, 1526 fp->hdr.type == BINDER_TYPE_BINDER,
1467 &thread->todo, &rdata); 1527 &thread->todo, &rdata);
1468 if (ret) 1528 if (ret)
1469 return ret; 1529 goto done;
1470 1530
1471 if (fp->hdr.type == BINDER_TYPE_BINDER) 1531 if (fp->hdr.type == BINDER_TYPE_BINDER)
1472 fp->hdr.type = BINDER_TYPE_HANDLE; 1532 fp->hdr.type = BINDER_TYPE_HANDLE;
@@ -1481,7 +1541,9 @@ static int binder_translate_binder(struct flat_binder_object *fp,
1481 " node %d u%016llx -> ref %d desc %d\n", 1541 " node %d u%016llx -> ref %d desc %d\n",
1482 node->debug_id, (u64)node->ptr, 1542 node->debug_id, (u64)node->ptr,
1483 rdata.debug_id, rdata.desc); 1543 rdata.debug_id, rdata.desc);
1484 return 0; 1544done:
1545 binder_put_node(node);
1546 return ret;
1485} 1547}
1486 1548
1487static int binder_translate_handle(struct flat_binder_object *fp, 1549static int binder_translate_handle(struct flat_binder_object *fp,
@@ -1492,6 +1554,7 @@ static int binder_translate_handle(struct flat_binder_object *fp,
1492 struct binder_proc *target_proc = t->to_proc; 1554 struct binder_proc *target_proc = t->to_proc;
1493 struct binder_node *node; 1555 struct binder_node *node;
1494 struct binder_ref_data src_rdata; 1556 struct binder_ref_data src_rdata;
1557 int ret = 0;
1495 1558
1496 node = binder_get_node_from_ref(proc, fp->handle, 1559 node = binder_get_node_from_ref(proc, fp->handle,
1497 fp->hdr.type == BINDER_TYPE_HANDLE, &src_rdata); 1560 fp->hdr.type == BINDER_TYPE_HANDLE, &src_rdata);
@@ -1500,8 +1563,10 @@ static int binder_translate_handle(struct flat_binder_object *fp,
1500 proc->pid, thread->pid, fp->handle); 1563 proc->pid, thread->pid, fp->handle);
1501 return -EINVAL; 1564 return -EINVAL;
1502 } 1565 }
1503 if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) 1566 if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) {
1504 return -EPERM; 1567 ret = -EPERM;
1568 goto done;
1569 }
1505 1570
1506 if (node->proc == target_proc) { 1571 if (node->proc == target_proc) {
1507 if (fp->hdr.type == BINDER_TYPE_HANDLE) 1572 if (fp->hdr.type == BINDER_TYPE_HANDLE)
@@ -1526,7 +1591,7 @@ static int binder_translate_handle(struct flat_binder_object *fp,
1526 fp->hdr.type == BINDER_TYPE_HANDLE, 1591 fp->hdr.type == BINDER_TYPE_HANDLE,
1527 NULL, &dest_rdata); 1592 NULL, &dest_rdata);
1528 if (ret) 1593 if (ret)
1529 return ret; 1594 goto done;
1530 1595
1531 fp->binder = 0; 1596 fp->binder = 0;
1532 fp->handle = dest_rdata.desc; 1597 fp->handle = dest_rdata.desc;
@@ -1539,7 +1604,9 @@ static int binder_translate_handle(struct flat_binder_object *fp,
1539 dest_rdata.debug_id, dest_rdata.desc, 1604 dest_rdata.debug_id, dest_rdata.desc,
1540 node->debug_id); 1605 node->debug_id);
1541 } 1606 }
1542 return 0; 1607done:
1608 binder_put_node(node);
1609 return ret;
1543} 1610}
1544 1611
1545static int binder_translate_fd(int fd, 1612static int binder_translate_fd(int fd,
@@ -2381,6 +2448,7 @@ static int binder_thread_write(struct binder_proc *proc,
2381 "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE", 2448 "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE",
2382 (u64)node_ptr, node->debug_id, 2449 (u64)node_ptr, node->debug_id,
2383 (u64)cookie, (u64)node->cookie); 2450 (u64)cookie, (u64)node->cookie);
2451 binder_put_node(node);
2384 break; 2452 break;
2385 } 2453 }
2386 if (cmd == BC_ACQUIRE_DONE) { 2454 if (cmd == BC_ACQUIRE_DONE) {
@@ -2388,6 +2456,7 @@ static int binder_thread_write(struct binder_proc *proc,
2388 binder_user_error("%d:%d BC_ACQUIRE_DONE node %d has no pending acquire request\n", 2456 binder_user_error("%d:%d BC_ACQUIRE_DONE node %d has no pending acquire request\n",
2389 proc->pid, thread->pid, 2457 proc->pid, thread->pid,
2390 node->debug_id); 2458 node->debug_id);
2459 binder_put_node(node);
2391 break; 2460 break;
2392 } 2461 }
2393 node->pending_strong_ref = 0; 2462 node->pending_strong_ref = 0;
@@ -2396,16 +2465,19 @@ static int binder_thread_write(struct binder_proc *proc,
2396 binder_user_error("%d:%d BC_INCREFS_DONE node %d has no pending increfs request\n", 2465 binder_user_error("%d:%d BC_INCREFS_DONE node %d has no pending increfs request\n",
2397 proc->pid, thread->pid, 2466 proc->pid, thread->pid,
2398 node->debug_id); 2467 node->debug_id);
2468 binder_put_node(node);
2399 break; 2469 break;
2400 } 2470 }
2401 node->pending_weak_ref = 0; 2471 node->pending_weak_ref = 0;
2402 } 2472 }
2403 binder_dec_node(node, cmd == BC_ACQUIRE_DONE, 0); 2473 binder_dec_node(node, cmd == BC_ACQUIRE_DONE, 0);
2404 binder_debug(BINDER_DEBUG_USER_REFS, 2474 binder_debug(BINDER_DEBUG_USER_REFS,
2405 "%d:%d %s node %d ls %d lw %d\n", 2475 "%d:%d %s node %d ls %d lw %d tr %d\n",
2406 proc->pid, thread->pid, 2476 proc->pid, thread->pid,
2407 cmd == BC_INCREFS_DONE ? "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE", 2477 cmd == BC_INCREFS_DONE ? "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE",
2408 node->debug_id, node->local_strong_refs, node->local_weak_refs); 2478 node->debug_id, node->local_strong_refs,
2479 node->local_weak_refs, node->tmp_refs);
2480 binder_put_node(node);
2409 break; 2481 break;
2410 } 2482 }
2411 case BC_ATTEMPT_ACQUIRE: 2483 case BC_ATTEMPT_ACQUIRE:
@@ -2845,7 +2917,8 @@ retry:
2845 strong = node->internal_strong_refs || 2917 strong = node->internal_strong_refs ||
2846 node->local_strong_refs; 2918 node->local_strong_refs;
2847 weak = !hlist_empty(&node->refs) || 2919 weak = !hlist_empty(&node->refs) ||
2848 node->local_weak_refs || strong; 2920 node->local_weak_refs ||
2921 node->tmp_refs || strong;
2849 has_strong_ref = node->has_strong_ref; 2922 has_strong_ref = node->has_strong_ref;
2850 has_weak_ref = node->has_weak_ref; 2923 has_weak_ref = node->has_weak_ref;
2851 2924
@@ -3357,6 +3430,7 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp)
3357 new_node->has_strong_ref = 1; 3430 new_node->has_strong_ref = 1;
3358 new_node->has_weak_ref = 1; 3431 new_node->has_weak_ref = 1;
3359 context->binder_context_mgr_node = new_node; 3432 context->binder_context_mgr_node = new_node;
3433 binder_put_node(new_node);
3360out: 3434out:
3361 mutex_unlock(&context->context_mgr_node_lock); 3435 mutex_unlock(&context->context_mgr_node_lock);
3362 return ret; 3436 return ret;
@@ -3615,8 +3689,11 @@ static int binder_node_release(struct binder_node *node, int refs)
3615 3689
3616 list_del_init(&node->work.entry); 3690 list_del_init(&node->work.entry);
3617 binder_release_work(&node->async_todo); 3691 binder_release_work(&node->async_todo);
3618 3692 /*
3619 if (hlist_empty(&node->refs)) { 3693 * The caller must have taken a temporary ref on the node,
3694 */
3695 BUG_ON(!node->tmp_refs);
3696 if (hlist_empty(&node->refs) && node->tmp_refs == 1) {
3620 kfree(node); 3697 kfree(node);
3621 binder_stats_deleted(BINDER_STAT_NODE); 3698 binder_stats_deleted(BINDER_STAT_NODE);
3622 3699
@@ -3651,6 +3728,7 @@ static int binder_node_release(struct binder_node *node, int refs)
3651 binder_debug(BINDER_DEBUG_DEAD_BINDER, 3728 binder_debug(BINDER_DEBUG_DEAD_BINDER,
3652 "node %d now dead, refs %d, death %d\n", 3729 "node %d now dead, refs %d, death %d\n",
3653 node->debug_id, refs, death); 3730 node->debug_id, refs, death);
3731 binder_put_node(node);
3654 3732
3655 return refs; 3733 return refs;
3656} 3734}
@@ -3700,6 +3778,12 @@ static void binder_deferred_release(struct binder_proc *proc)
3700 3778
3701 node = rb_entry(n, struct binder_node, rb_node); 3779 node = rb_entry(n, struct binder_node, rb_node);
3702 nodes++; 3780 nodes++;
3781 /*
3782 * take a temporary ref on the node before
3783 * calling binder_node_release() which will either
3784 * kfree() the node or call binder_put_node()
3785 */
3786 binder_inc_node_tmpref(node);
3703 rb_erase(&node->rb_node, &proc->nodes); 3787 rb_erase(&node->rb_node, &proc->nodes);
3704 incoming_refs = binder_node_release(node, incoming_refs); 3788 incoming_refs = binder_node_release(node, incoming_refs);
3705 } 3789 }
@@ -3895,11 +3979,11 @@ static void print_binder_node(struct seq_file *m, struct binder_node *node)
3895 hlist_for_each_entry(ref, &node->refs, node_entry) 3979 hlist_for_each_entry(ref, &node->refs, node_entry)
3896 count++; 3980 count++;
3897 3981
3898 seq_printf(m, " node %d: u%016llx c%016llx hs %d hw %d ls %d lw %d is %d iw %d", 3982 seq_printf(m, " node %d: u%016llx c%016llx hs %d hw %d ls %d lw %d is %d iw %d tr %d",
3899 node->debug_id, (u64)node->ptr, (u64)node->cookie, 3983 node->debug_id, (u64)node->ptr, (u64)node->cookie,
3900 node->has_strong_ref, node->has_weak_ref, 3984 node->has_strong_ref, node->has_weak_ref,
3901 node->local_strong_refs, node->local_weak_refs, 3985 node->local_strong_refs, node->local_weak_refs,
3902 node->internal_strong_refs, count); 3986 node->internal_strong_refs, count, node->tmp_refs);
3903 if (count) { 3987 if (count) {
3904 seq_puts(m, " proc"); 3988 seq_puts(m, " proc");
3905 hlist_for_each_entry(ref, &node->refs, node_entry) 3989 hlist_for_each_entry(ref, &node->refs, node_entry)