diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-10-15 07:50:38 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-10-15 07:50:38 -0400 |
commit | ae7df8f985f1b0445366ae6f6324cd08a218526e (patch) | |
tree | 7531517ec51cab79594fea13157f9a1a77d67d57 /drivers/android | |
parent | 7a263b16c5a258b2f3fe5b58a7c461cc9d34e99a (diff) | |
parent | 512cf465ee01eb23936a9e6ed0b6414eccb00853 (diff) |
Merge tag 'char-misc-4.14-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc driver fixes from Greg KH:
"Here are 4 patches to resolve some char/misc driver issues found these
past weeks.
One of them is a mei bugfix and another is a new mei device id. There
is also a hyper-v fix for a reported issue, and a binder issue fix for
a problem reported by a few people.
All of these have been in my tree for a while, I don't know if
linux-next is really testing much this month. But 0-day is happy with
them :)"
* tag 'char-misc-4.14-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc:
binder: fix use-after-free in binder_transaction()
Drivers: hv: vmbus: Fix bugs in rescind handling
mei: me: add gemini lake devices id
mei: always use domain runtime pm callbacks.
Diffstat (limited to 'drivers/android')
-rw-r--r-- | drivers/android/binder.c | 93 |
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 | */ | ||
2606 | static 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 | |||
2585 | static void binder_transaction(struct binder_proc *proc, | 2627 | static 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: | |||
3090 | err_copy_data_failed: | 3126 | err_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: | |||
3104 | err_empty_call_stack: | 3142 | err_empty_call_stack: |
3105 | err_dead_binder: | 3143 | err_dead_binder: |
3106 | err_invalid_target_handle: | 3144 | err_invalid_target_handle: |
3107 | err_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", |