@@ -2582,6 +2582,48 @@ static bool binder_proc_transaction(struct binder_transaction *t,
2582
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
2627
static void binder_transaction (struct binder_proc * proc ,
2586
2628
struct binder_thread * thread ,
2587
2629
struct binder_transaction_data * tr , int reply ,
@@ -2685,43 +2727,35 @@ static void binder_transaction(struct binder_proc *proc,
2685
2727
ref = binder_get_ref_olocked (proc , tr -> target .handle ,
2686
2728
true);
2687
2729
if (ref ) {
2688
- binder_inc_node (ref -> node , 1 , 0 , NULL );
2689
- target_node = ref -> node ;
2690
- }
2691
- binder_proc_unlock (proc );
2692
- if (target_node == NULL ) {
2730
+ target_node = binder_get_node_refs_for_txn (
2731
+ ref -> node , & target_proc ,
2732
+ & return_error );
2733
+ } else {
2693
2734
binder_user_error ("%d:%d got transaction to invalid handle\n" ,
2694
- proc -> pid , thread -> pid );
2735
+ proc -> pid , thread -> pid );
2695
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
2739
} else {
2701
2740
mutex_lock (& context -> context_mgr_node_lock );
2702
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
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
2748
mutex_unlock (& context -> context_mgr_node_lock );
2711
2749
}
2712
- e -> to_node = target_node -> debug_id ;
2713
- binder_node_lock (target_node );
2714
- target_proc = target_node -> proc ;
2715
- if (target_proc == NULL ) {
2716
- binder_node_unlock (target_node );
2717
- return_error = BR_DEAD_REPLY ;
2750
+ if (!target_node ) {
2751
+ /*
2752
+ * return_error is set above
2753
+ */
2754
+ return_error_param = - EINVAL ;
2718
2755
return_error_line = __LINE__ ;
2719
2756
goto err_dead_binder ;
2720
2757
}
2721
- binder_inner_proc_lock (target_proc );
2722
- target_proc -> tmp_ref ++ ;
2723
- binder_inner_proc_unlock (target_proc );
2724
- binder_node_unlock (target_node );
2758
+ e -> to_node = target_node -> debug_id ;
2725
2759
if (security_binder_transaction (proc -> tsk ,
2726
2760
target_proc -> tsk ) < 0 ) {
2727
2761
return_error = BR_FAILED_REPLY ;
@@ -3071,6 +3105,8 @@ static void binder_transaction(struct binder_proc *proc,
3071
3105
if (target_thread )
3072
3106
binder_thread_dec_tmpref (target_thread );
3073
3107
binder_proc_dec_tmpref (target_proc );
3108
+ if (target_node )
3109
+ binder_dec_node_tmpref (target_node );
3074
3110
/*
3075
3111
* write barrier to synchronize with initialization
3076
3112
* of log entry
@@ -3090,6 +3126,8 @@ static void binder_transaction(struct binder_proc *proc,
3090
3126
err_copy_data_failed :
3091
3127
trace_binder_transaction_failed_buffer_release (t -> buffer );
3092
3128
binder_transaction_buffer_release (target_proc , t -> buffer , offp );
3129
+ if (target_node )
3130
+ binder_dec_node_tmpref (target_node );
3093
3131
target_node = NULL ;
3094
3132
t -> buffer -> transaction = NULL ;
3095
3133
binder_alloc_free_buf (& target_proc -> alloc , t -> buffer );
@@ -3104,13 +3142,14 @@ static void binder_transaction(struct binder_proc *proc,
3104
3142
err_empty_call_stack :
3105
3143
err_dead_binder :
3106
3144
err_invalid_target_handle :
3107
- err_no_context_mgr_node :
3108
3145
if (target_thread )
3109
3146
binder_thread_dec_tmpref (target_thread );
3110
3147
if (target_proc )
3111
3148
binder_proc_dec_tmpref (target_proc );
3112
- if (target_node )
3149
+ if (target_node ) {
3113
3150
binder_dec_node (target_node , 1 , 0 );
3151
+ binder_dec_node_tmpref (target_node );
3152
+ }
3114
3153
3115
3154
binder_debug (BINDER_DEBUG_FAILED_TRANSACTION ,
3116
3155
"%d:%d transaction failed %d/%d, size %lld-%lld line %d\n" ,
0 commit comments