@@ -2582,6 +2582,48 @@ static bool binder_proc_transaction(struct binder_transaction *t,
25822582 return true;
25832583}
25842584
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+
25852627static void binder_transaction (struct binder_proc * proc ,
25862628 struct binder_thread * thread ,
25872629 struct binder_transaction_data * tr , int reply ,
@@ -2685,43 +2727,35 @@ static void binder_transaction(struct binder_proc *proc,
26852727 ref = binder_get_ref_olocked (proc , tr -> target .handle ,
26862728 true);
26872729 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 {
26932734 binder_user_error ("%d:%d got transaction to invalid handle\n" ,
2694- proc -> pid , thread -> pid );
2735+ proc -> pid , thread -> pid );
26952736 return_error = BR_FAILED_REPLY ;
2696- return_error_param = - EINVAL ;
2697- return_error_line = __LINE__ ;
2698- goto err_invalid_target_handle ;
26992737 }
2738+ binder_proc_unlock (proc );
27002739 } else {
27012740 mutex_lock (& context -> context_mgr_node_lock );
27022741 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
27042747 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 );
27102748 mutex_unlock (& context -> context_mgr_node_lock );
27112749 }
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 ;
27182755 return_error_line = __LINE__ ;
27192756 goto err_dead_binder ;
27202757 }
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 ;
27252759 if (security_binder_transaction (proc -> tsk ,
27262760 target_proc -> tsk ) < 0 ) {
27272761 return_error = BR_FAILED_REPLY ;
@@ -3071,6 +3105,8 @@ static void binder_transaction(struct binder_proc *proc,
30713105 if (target_thread )
30723106 binder_thread_dec_tmpref (target_thread );
30733107 binder_proc_dec_tmpref (target_proc );
3108+ if (target_node )
3109+ binder_dec_node_tmpref (target_node );
30743110 /*
30753111 * write barrier to synchronize with initialization
30763112 * of log entry
@@ -3090,6 +3126,8 @@ static void binder_transaction(struct binder_proc *proc,
30903126err_copy_data_failed :
30913127 trace_binder_transaction_failed_buffer_release (t -> buffer );
30923128 binder_transaction_buffer_release (target_proc , t -> buffer , offp );
3129+ if (target_node )
3130+ binder_dec_node_tmpref (target_node );
30933131 target_node = NULL ;
30943132 t -> buffer -> transaction = NULL ;
30953133 binder_alloc_free_buf (& target_proc -> alloc , t -> buffer );
@@ -3104,13 +3142,14 @@ static void binder_transaction(struct binder_proc *proc,
31043142err_empty_call_stack :
31053143err_dead_binder :
31063144err_invalid_target_handle :
3107- err_no_context_mgr_node :
31083145 if (target_thread )
31093146 binder_thread_dec_tmpref (target_thread );
31103147 if (target_proc )
31113148 binder_proc_dec_tmpref (target_proc );
3112- if (target_node )
3149+ if (target_node ) {
31133150 binder_dec_node (target_node , 1 , 0 );
3151+ binder_dec_node_tmpref (target_node );
3152+ }
31143153
31153154 binder_debug (BINDER_DEBUG_FAILED_TRANSACTION ,
31163155 "%d:%d transaction failed %d/%d, size %lld-%lld line %d\n" ,
0 commit comments