@@ -2744,6 +2744,48 @@ static bool binder_proc_transaction(struct binder_transaction *t,
27442744 return true;
27452745}
27462746
2747+ /**
2748+ * binder_get_node_refs_for_txn() - Get required refs on node for txn
2749+ * @node: struct binder_node for which to get refs
2750+ * @proc: returns @node->proc if valid
2751+ * @error: if no @proc then returns BR_DEAD_REPLY
2752+ *
2753+ * User-space normally keeps the node alive when creating a transaction
2754+ * since it has a reference to the target. The local strong ref keeps it
2755+ * alive if the sending process dies before the target process processes
2756+ * the transaction. If the source process is malicious or has a reference
2757+ * counting bug, relying on the local strong ref can fail.
2758+ *
2759+ * Since user-space can cause the local strong ref to go away, we also take
2760+ * a tmpref on the node to ensure it survives while we are constructing
2761+ * the transaction. We also need a tmpref on the proc while we are
2762+ * constructing the transaction, so we take that here as well.
2763+ *
2764+ * Return: The target_node with refs taken or NULL if no @node->proc is NULL.
2765+ * Also sets @proc if valid. If the @node->proc is NULL indicating that the
2766+ * target proc has died, @error is set to BR_DEAD_REPLY
2767+ */
2768+ static struct binder_node * binder_get_node_refs_for_txn (
2769+ struct binder_node * node ,
2770+ struct binder_proc * * procp ,
2771+ uint32_t * error )
2772+ {
2773+ struct binder_node * target_node = NULL ;
2774+
2775+ binder_node_inner_lock (node );
2776+ if (node -> proc ) {
2777+ target_node = node ;
2778+ binder_inc_node_nilocked (node , 1 , 0 , NULL );
2779+ binder_inc_node_tmpref_ilocked (node );
2780+ node -> proc -> tmp_ref ++ ;
2781+ * procp = node -> proc ;
2782+ } else
2783+ * error = BR_DEAD_REPLY ;
2784+ binder_node_inner_unlock (node );
2785+
2786+ return target_node ;
2787+ }
2788+
27472789static void binder_transaction (struct binder_proc * proc ,
27482790 struct binder_thread * thread ,
27492791 struct binder_transaction_data * tr , int reply ,
@@ -2846,43 +2888,35 @@ static void binder_transaction(struct binder_proc *proc,
28462888 ref = binder_get_ref_olocked (proc , tr -> target .handle ,
28472889 true);
28482890 if (ref ) {
2849- binder_inc_node (ref -> node , 1 , 0 , NULL );
2850- target_node = ref -> node ;
2851- }
2852- binder_proc_unlock (proc );
2853- if (target_node == NULL ) {
2891+ target_node = binder_get_node_refs_for_txn (
2892+ ref -> node , & target_proc ,
2893+ & return_error );
2894+ } else {
28542895 binder_user_error ("%d:%d got transaction to invalid handle\n" ,
2855- proc -> pid , thread -> pid );
2896+ proc -> pid , thread -> pid );
28562897 return_error = BR_FAILED_REPLY ;
2857- return_error_param = - EINVAL ;
2858- return_error_line = __LINE__ ;
2859- goto err_invalid_target_handle ;
28602898 }
2899+ binder_proc_unlock (proc );
28612900 } else {
28622901 mutex_lock (& context -> context_mgr_node_lock );
28632902 target_node = context -> binder_context_mgr_node ;
2864- if (target_node == NULL ) {
2903+ if (target_node )
2904+ target_node = binder_get_node_refs_for_txn (
2905+ target_node , & target_proc ,
2906+ & return_error );
2907+ else
28652908 return_error = BR_DEAD_REPLY ;
2866- mutex_unlock (& context -> context_mgr_node_lock );
2867- return_error_line = __LINE__ ;
2868- goto err_no_context_mgr_node ;
2869- }
2870- binder_inc_node (target_node , 1 , 0 , NULL );
28712909 mutex_unlock (& context -> context_mgr_node_lock );
28722910 }
2873- e -> to_node = target_node -> debug_id ;
2874- binder_node_lock (target_node );
2875- target_proc = target_node -> proc ;
2876- if (target_proc == NULL ) {
2877- binder_node_unlock (target_node );
2878- return_error = BR_DEAD_REPLY ;
2911+ if (!target_node ) {
2912+ /*
2913+ * return_error is set above
2914+ */
2915+ return_error_param = - EINVAL ;
28792916 return_error_line = __LINE__ ;
28802917 goto err_dead_binder ;
28812918 }
2882- binder_inner_proc_lock (target_proc );
2883- target_proc -> tmp_ref ++ ;
2884- binder_inner_proc_unlock (target_proc );
2885- binder_node_unlock (target_node );
2919+ e -> to_node = target_node -> debug_id ;
28862920 if (security_binder_transaction (proc -> tsk ,
28872921 target_proc -> tsk ) < 0 ) {
28882922 return_error = BR_FAILED_REPLY ;
@@ -3241,6 +3275,8 @@ static void binder_transaction(struct binder_proc *proc,
32413275 if (target_thread )
32423276 binder_thread_dec_tmpref (target_thread );
32433277 binder_proc_dec_tmpref (target_proc );
3278+ if (target_node )
3279+ binder_dec_node_tmpref (target_node );
32443280 /*
32453281 * write barrier to synchronize with initialization
32463282 * of log entry
@@ -3260,6 +3296,8 @@ static void binder_transaction(struct binder_proc *proc,
32603296err_copy_data_failed :
32613297 trace_binder_transaction_failed_buffer_release (t -> buffer );
32623298 binder_transaction_buffer_release (target_proc , t -> buffer , offp );
3299+ if (target_node )
3300+ binder_dec_node_tmpref (target_node );
32633301 target_node = NULL ;
32643302 t -> buffer -> transaction = NULL ;
32653303 binder_alloc_free_buf (& target_proc -> alloc , t -> buffer );
@@ -3274,13 +3312,14 @@ static void binder_transaction(struct binder_proc *proc,
32743312err_empty_call_stack :
32753313err_dead_binder :
32763314err_invalid_target_handle :
3277- err_no_context_mgr_node :
32783315 if (target_thread )
32793316 binder_thread_dec_tmpref (target_thread );
32803317 if (target_proc )
32813318 binder_proc_dec_tmpref (target_proc );
3282- if (target_node )
3319+ if (target_node ) {
32833320 binder_dec_node (target_node , 1 , 0 );
3321+ binder_dec_node_tmpref (target_node );
3322+ }
32843323
32853324 binder_debug (BINDER_DEBUG_FAILED_TRANSACTION ,
32863325 "%d:%d transaction failed %d/%d, size %lld-%lld line %d\n" ,
0 commit comments