aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTodd Kjos <tkjos@android.com>2017-09-29 18:39:49 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-10-04 05:25:10 -0400
commit512cf465ee01eb23936a9e6ed0b6414eccb00853 (patch)
treeacd6475a037326bd58015094502d79b42165c436
parent192b2d78722ffea188e5ec6ae5d55010dce05a4b (diff)
binder: fix use-after-free in binder_transaction()
User-space normally keeps the node alive when creating a transaction since it has a reference to the target. The local strong ref keeps it alive if the sending process dies before the target process processes the transaction. If the source process is malicious or has a reference counting bug, this can fail. In this case, when we attempt to decrement the node in the failure path, the node has already been freed. This is fixed by taking a tmpref on the node while constructing the transaction. To avoid re-acquiring the node lock and inner proc lock to increment the proc's tmpref, a helper is used that does the ref increments on both the node and proc. Signed-off-by: Todd Kjos <tkjos@google.com> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/android/binder.c93
1 files changed, 66 insertions, 27 deletions
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index ab34239a76ee..0621a95b8597 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2582,6 +2582,48 @@ static bool binder_proc_transaction(struct binder_transaction *t,
2582 return true; 2582 return true;
2583} 2583}
2584 2584
2585/**
2586 * binder_get_node_refs_for_txn() - Get required refs on node for txn
2587 * @node: struct binder_node for which to get refs
2588 * @proc: returns @node->proc if valid
2589 * @error: if no @proc then returns BR_DEAD_REPLY
2590 *
2591 * User-space normally keeps the node alive when creating a transaction
2592 * since it has a reference to the target. The local strong ref keeps it
2593 * alive if the sending process dies before the target process processes
2594 * the transaction. If the source process is malicious or has a reference
2595 * counting bug, relying on the local strong ref can fail.
2596 *
2597 * Since user-space can cause the local strong ref to go away, we also take
2598 * a tmpref on the node to ensure it survives while we are constructing
2599 * the transaction. We also need a tmpref on the proc while we are
2600 * constructing the transaction, so we take that here as well.
2601 *
2602 * Return: The target_node with refs taken or NULL if no @node->proc is NULL.
2603 * Also sets @proc if valid. If the @node->proc is NULL indicating that the
2604 * target proc has died, @error is set to BR_DEAD_REPLY
2605 */
2606static struct binder_node *binder_get_node_refs_for_txn(
2607 struct binder_node *node,
2608 struct binder_proc **procp,
2609 uint32_t *error)
2610{
2611 struct binder_node *target_node = NULL;
2612
2613 binder_node_inner_lock(node);
2614 if (node->proc) {
2615 target_node = node;
2616 binder_inc_node_nilocked(node, 1, 0, NULL);
2617 binder_inc_node_tmpref_ilocked(node);
2618 node->proc->tmp_ref++;
2619 *procp = node->proc;
2620 } else
2621 *error = BR_DEAD_REPLY;
2622 binder_node_inner_unlock(node);
2623
2624 return target_node;
2625}
2626
2585static void binder_transaction(struct binder_proc *proc, 2627static void binder_transaction(struct binder_proc *proc,
2586 struct binder_thread *thread, 2628 struct binder_thread *thread,
2587 struct binder_transaction_data *tr, int reply, 2629 struct binder_transaction_data *tr, int reply,
@@ -2685,43 +2727,35 @@ static void binder_transaction(struct binder_proc *proc,
2685 ref = binder_get_ref_olocked(proc, tr->target.handle, 2727 ref = binder_get_ref_olocked(proc, tr->target.handle,
2686 true); 2728 true);
2687 if (ref) { 2729 if (ref) {
2688 binder_inc_node(ref->node, 1, 0, NULL); 2730 target_node = binder_get_node_refs_for_txn(
2689 target_node = ref->node; 2731 ref->node, &target_proc,
2690 } 2732 &return_error);
2691 binder_proc_unlock(proc); 2733 } else {
2692 if (target_node == NULL) {
2693 binder_user_error("%d:%d got transaction to invalid handle\n", 2734 binder_user_error("%d:%d got transaction to invalid handle\n",
2694 proc->pid, thread->pid); 2735 proc->pid, thread->pid);
2695 return_error = BR_FAILED_REPLY; 2736 return_error = BR_FAILED_REPLY;
2696 return_error_param = -EINVAL;
2697 return_error_line = __LINE__;
2698 goto err_invalid_target_handle;
2699 } 2737 }
2738 binder_proc_unlock(proc);
2700 } else { 2739 } else {
2701 mutex_lock(&context->context_mgr_node_lock); 2740 mutex_lock(&context->context_mgr_node_lock);
2702 target_node = context->binder_context_mgr_node; 2741 target_node = context->binder_context_mgr_node;
2703 if (target_node == NULL) { 2742 if (target_node)
2743 target_node = binder_get_node_refs_for_txn(
2744 target_node, &target_proc,
2745 &return_error);
2746 else
2704 return_error = BR_DEAD_REPLY; 2747 return_error = BR_DEAD_REPLY;
2705 mutex_unlock(&context->context_mgr_node_lock);
2706 return_error_line = __LINE__;
2707 goto err_no_context_mgr_node;
2708 }
2709 binder_inc_node(target_node, 1, 0, NULL);
2710 mutex_unlock(&context->context_mgr_node_lock); 2748 mutex_unlock(&context->context_mgr_node_lock);
2711 } 2749 }
2712 e->to_node = target_node->debug_id; 2750 if (!target_node) {
2713 binder_node_lock(target_node); 2751 /*
2714 target_proc = target_node->proc; 2752 * return_error is set above
2715 if (target_proc == NULL) { 2753 */
2716 binder_node_unlock(target_node); 2754 return_error_param = -EINVAL;
2717 return_error = BR_DEAD_REPLY;
2718 return_error_line = __LINE__; 2755 return_error_line = __LINE__;
2719 goto err_dead_binder; 2756 goto err_dead_binder;
2720 } 2757 }
2721 binder_inner_proc_lock(target_proc); 2758 e->to_node = target_node->debug_id;
2722 target_proc->tmp_ref++;
2723 binder_inner_proc_unlock(target_proc);
2724 binder_node_unlock(target_node);
2725 if (security_binder_transaction(proc->tsk, 2759 if (security_binder_transaction(proc->tsk,
2726 target_proc->tsk) < 0) { 2760 target_proc->tsk) < 0) {
2727 return_error = BR_FAILED_REPLY; 2761 return_error = BR_FAILED_REPLY;
@@ -3071,6 +3105,8 @@ static void binder_transaction(struct binder_proc *proc,
3071 if (target_thread) 3105 if (target_thread)
3072 binder_thread_dec_tmpref(target_thread); 3106 binder_thread_dec_tmpref(target_thread);
3073 binder_proc_dec_tmpref(target_proc); 3107 binder_proc_dec_tmpref(target_proc);
3108 if (target_node)
3109 binder_dec_node_tmpref(target_node);
3074 /* 3110 /*
3075 * write barrier to synchronize with initialization 3111 * write barrier to synchronize with initialization
3076 * of log entry 3112 * of log entry
@@ -3090,6 +3126,8 @@ err_bad_parent:
3090err_copy_data_failed: 3126err_copy_data_failed:
3091 trace_binder_transaction_failed_buffer_release(t->buffer); 3127 trace_binder_transaction_failed_buffer_release(t->buffer);
3092 binder_transaction_buffer_release(target_proc, t->buffer, offp); 3128 binder_transaction_buffer_release(target_proc, t->buffer, offp);
3129 if (target_node)
3130 binder_dec_node_tmpref(target_node);
3093 target_node = NULL; 3131 target_node = NULL;
3094 t->buffer->transaction = NULL; 3132 t->buffer->transaction = NULL;
3095 binder_alloc_free_buf(&target_proc->alloc, t->buffer); 3133 binder_alloc_free_buf(&target_proc->alloc, t->buffer);
@@ -3104,13 +3142,14 @@ err_bad_call_stack:
3104err_empty_call_stack: 3142err_empty_call_stack:
3105err_dead_binder: 3143err_dead_binder:
3106err_invalid_target_handle: 3144err_invalid_target_handle:
3107err_no_context_mgr_node:
3108 if (target_thread) 3145 if (target_thread)
3109 binder_thread_dec_tmpref(target_thread); 3146 binder_thread_dec_tmpref(target_thread);
3110 if (target_proc) 3147 if (target_proc)
3111 binder_proc_dec_tmpref(target_proc); 3148 binder_proc_dec_tmpref(target_proc);
3112 if (target_node) 3149 if (target_node) {
3113 binder_dec_node(target_node, 1, 0); 3150 binder_dec_node(target_node, 1, 0);
3151 binder_dec_node_tmpref(target_node);
3152 }
3114 3153
3115 binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, 3154 binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
3116 "%d:%d transaction failed %d/%d, size %lld-%lld line %d\n", 3155 "%d:%d transaction failed %d/%d, size %lld-%lld line %d\n",