lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Fri, 11 Jan 2019 11:07:36 +0800
From:   kbuild test robot <lkp@...el.com>
To:     Todd Kjos <tkjos@...roid.com>
Cc:     kbuild-all@...org, tkjos@...gle.com, gregkh@...uxfoundation.org,
        arve@...roid.com, devel@...verdev.osuosl.org,
        linux-kernel@...r.kernel.org, maco@...gle.com,
        joel@...lfernandes.org, kernel-team@...roid.com
Subject: Re: [PATCH] binder: create node flag to request sender's security
 context

Hi Todd,

I love your patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v5.0-rc1 next-20190110]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Todd-Kjos/binder-create-node-flag-to-request-sender-s-security-context/20190111-095225
config: i386-randconfig-x009-201901 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All warnings (new ones prefixed by >>):

   drivers/android/binder.c: In function 'binder_transaction':
>> drivers/android/binder.c:3067:21: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
      t->security_ctx = (binder_uintptr_t)kptr +
                        ^

vim +3067 drivers/android/binder.c

  2761	
  2762	static void binder_transaction(struct binder_proc *proc,
  2763				       struct binder_thread *thread,
  2764				       struct binder_transaction_data *tr, int reply,
  2765				       binder_size_t extra_buffers_size)
  2766	{
  2767		int ret;
  2768		struct binder_transaction *t;
  2769		struct binder_work *w;
  2770		struct binder_work *tcomplete;
  2771		binder_size_t *offp, *off_end, *off_start;
  2772		binder_size_t off_min;
  2773		u8 *sg_bufp, *sg_buf_end;
  2774		struct binder_proc *target_proc = NULL;
  2775		struct binder_thread *target_thread = NULL;
  2776		struct binder_node *target_node = NULL;
  2777		struct binder_transaction *in_reply_to = NULL;
  2778		struct binder_transaction_log_entry *e;
  2779		uint32_t return_error = 0;
  2780		uint32_t return_error_param = 0;
  2781		uint32_t return_error_line = 0;
  2782		struct binder_buffer_object *last_fixup_obj = NULL;
  2783		binder_size_t last_fixup_min_off = 0;
  2784		struct binder_context *context = proc->context;
  2785		int t_debug_id = atomic_inc_return(&binder_last_id);
  2786		char *secctx = NULL;
  2787		u32 secctx_sz = 0;
  2788	
  2789		e = binder_transaction_log_add(&binder_transaction_log);
  2790		e->debug_id = t_debug_id;
  2791		e->call_type = reply ? 2 : !!(tr->flags & TF_ONE_WAY);
  2792		e->from_proc = proc->pid;
  2793		e->from_thread = thread->pid;
  2794		e->target_handle = tr->target.handle;
  2795		e->data_size = tr->data_size;
  2796		e->offsets_size = tr->offsets_size;
  2797		e->context_name = proc->context->name;
  2798	
  2799		if (reply) {
  2800			binder_inner_proc_lock(proc);
  2801			in_reply_to = thread->transaction_stack;
  2802			if (in_reply_to == NULL) {
  2803				binder_inner_proc_unlock(proc);
  2804				binder_user_error("%d:%d got reply transaction with no transaction stack\n",
  2805						  proc->pid, thread->pid);
  2806				return_error = BR_FAILED_REPLY;
  2807				return_error_param = -EPROTO;
  2808				return_error_line = __LINE__;
  2809				goto err_empty_call_stack;
  2810			}
  2811			if (in_reply_to->to_thread != thread) {
  2812				spin_lock(&in_reply_to->lock);
  2813				binder_user_error("%d:%d got reply transaction with bad transaction stack, transaction %d has target %d:%d\n",
  2814					proc->pid, thread->pid, in_reply_to->debug_id,
  2815					in_reply_to->to_proc ?
  2816					in_reply_to->to_proc->pid : 0,
  2817					in_reply_to->to_thread ?
  2818					in_reply_to->to_thread->pid : 0);
  2819				spin_unlock(&in_reply_to->lock);
  2820				binder_inner_proc_unlock(proc);
  2821				return_error = BR_FAILED_REPLY;
  2822				return_error_param = -EPROTO;
  2823				return_error_line = __LINE__;
  2824				in_reply_to = NULL;
  2825				goto err_bad_call_stack;
  2826			}
  2827			thread->transaction_stack = in_reply_to->to_parent;
  2828			binder_inner_proc_unlock(proc);
  2829			binder_set_nice(in_reply_to->saved_priority);
  2830			target_thread = binder_get_txn_from_and_acq_inner(in_reply_to);
  2831			if (target_thread == NULL) {
  2832				/* annotation for sparse */
  2833				__release(&target_thread->proc->inner_lock);
  2834				return_error = BR_DEAD_REPLY;
  2835				return_error_line = __LINE__;
  2836				goto err_dead_binder;
  2837			}
  2838			if (target_thread->transaction_stack != in_reply_to) {
  2839				binder_user_error("%d:%d got reply transaction with bad target transaction stack %d, expected %d\n",
  2840					proc->pid, thread->pid,
  2841					target_thread->transaction_stack ?
  2842					target_thread->transaction_stack->debug_id : 0,
  2843					in_reply_to->debug_id);
  2844				binder_inner_proc_unlock(target_thread->proc);
  2845				return_error = BR_FAILED_REPLY;
  2846				return_error_param = -EPROTO;
  2847				return_error_line = __LINE__;
  2848				in_reply_to = NULL;
  2849				target_thread = NULL;
  2850				goto err_dead_binder;
  2851			}
  2852			target_proc = target_thread->proc;
  2853			target_proc->tmp_ref++;
  2854			binder_inner_proc_unlock(target_thread->proc);
  2855		} else {
  2856			if (tr->target.handle) {
  2857				struct binder_ref *ref;
  2858	
  2859				/*
  2860				 * There must already be a strong ref
  2861				 * on this node. If so, do a strong
  2862				 * increment on the node to ensure it
  2863				 * stays alive until the transaction is
  2864				 * done.
  2865				 */
  2866				binder_proc_lock(proc);
  2867				ref = binder_get_ref_olocked(proc, tr->target.handle,
  2868							     true);
  2869				if (ref) {
  2870					target_node = binder_get_node_refs_for_txn(
  2871							ref->node, &target_proc,
  2872							&return_error);
  2873				} else {
  2874					binder_user_error("%d:%d got transaction to invalid handle\n",
  2875							  proc->pid, thread->pid);
  2876					return_error = BR_FAILED_REPLY;
  2877				}
  2878				binder_proc_unlock(proc);
  2879			} else {
  2880				mutex_lock(&context->context_mgr_node_lock);
  2881				target_node = context->binder_context_mgr_node;
  2882				if (target_node)
  2883					target_node = binder_get_node_refs_for_txn(
  2884							target_node, &target_proc,
  2885							&return_error);
  2886				else
  2887					return_error = BR_DEAD_REPLY;
  2888				mutex_unlock(&context->context_mgr_node_lock);
  2889				if (target_node && target_proc == proc) {
  2890					binder_user_error("%d:%d got transaction to context manager from process owning it\n",
  2891							  proc->pid, thread->pid);
  2892					return_error = BR_FAILED_REPLY;
  2893					return_error_param = -EINVAL;
  2894					return_error_line = __LINE__;
  2895					goto err_invalid_target_handle;
  2896				}
  2897			}
  2898			if (!target_node) {
  2899				/*
  2900				 * return_error is set above
  2901				 */
  2902				return_error_param = -EINVAL;
  2903				return_error_line = __LINE__;
  2904				goto err_dead_binder;
  2905			}
  2906			e->to_node = target_node->debug_id;
  2907			if (security_binder_transaction(proc->tsk,
  2908							target_proc->tsk) < 0) {
  2909				return_error = BR_FAILED_REPLY;
  2910				return_error_param = -EPERM;
  2911				return_error_line = __LINE__;
  2912				goto err_invalid_target_handle;
  2913			}
  2914			binder_inner_proc_lock(proc);
  2915	
  2916			w = list_first_entry_or_null(&thread->todo,
  2917						     struct binder_work, entry);
  2918			if (!(tr->flags & TF_ONE_WAY) && w &&
  2919			    w->type == BINDER_WORK_TRANSACTION) {
  2920				/*
  2921				 * Do not allow new outgoing transaction from a
  2922				 * thread that has a transaction at the head of
  2923				 * its todo list. Only need to check the head
  2924				 * because binder_select_thread_ilocked picks a
  2925				 * thread from proc->waiting_threads to enqueue
  2926				 * the transaction, and nothing is queued to the
  2927				 * todo list while the thread is on waiting_threads.
  2928				 */
  2929				binder_user_error("%d:%d new transaction not allowed when there is a transaction on thread todo\n",
  2930						  proc->pid, thread->pid);
  2931				binder_inner_proc_unlock(proc);
  2932				return_error = BR_FAILED_REPLY;
  2933				return_error_param = -EPROTO;
  2934				return_error_line = __LINE__;
  2935				goto err_bad_todo_list;
  2936			}
  2937	
  2938			if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) {
  2939				struct binder_transaction *tmp;
  2940	
  2941				tmp = thread->transaction_stack;
  2942				if (tmp->to_thread != thread) {
  2943					spin_lock(&tmp->lock);
  2944					binder_user_error("%d:%d got new transaction with bad transaction stack, transaction %d has target %d:%d\n",
  2945						proc->pid, thread->pid, tmp->debug_id,
  2946						tmp->to_proc ? tmp->to_proc->pid : 0,
  2947						tmp->to_thread ?
  2948						tmp->to_thread->pid : 0);
  2949					spin_unlock(&tmp->lock);
  2950					binder_inner_proc_unlock(proc);
  2951					return_error = BR_FAILED_REPLY;
  2952					return_error_param = -EPROTO;
  2953					return_error_line = __LINE__;
  2954					goto err_bad_call_stack;
  2955				}
  2956				while (tmp) {
  2957					struct binder_thread *from;
  2958	
  2959					spin_lock(&tmp->lock);
  2960					from = tmp->from;
  2961					if (from && from->proc == target_proc) {
  2962						atomic_inc(&from->tmp_ref);
  2963						target_thread = from;
  2964						spin_unlock(&tmp->lock);
  2965						break;
  2966					}
  2967					spin_unlock(&tmp->lock);
  2968					tmp = tmp->from_parent;
  2969				}
  2970			}
  2971			binder_inner_proc_unlock(proc);
  2972		}
  2973		if (target_thread)
  2974			e->to_thread = target_thread->pid;
  2975		e->to_proc = target_proc->pid;
  2976	
  2977		/* TODO: reuse incoming transaction for reply */
  2978		t = kzalloc(sizeof(*t), GFP_KERNEL);
  2979		if (t == NULL) {
  2980			return_error = BR_FAILED_REPLY;
  2981			return_error_param = -ENOMEM;
  2982			return_error_line = __LINE__;
  2983			goto err_alloc_t_failed;
  2984		}
  2985		INIT_LIST_HEAD(&t->fd_fixups);
  2986		binder_stats_created(BINDER_STAT_TRANSACTION);
  2987		spin_lock_init(&t->lock);
  2988	
  2989		tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
  2990		if (tcomplete == NULL) {
  2991			return_error = BR_FAILED_REPLY;
  2992			return_error_param = -ENOMEM;
  2993			return_error_line = __LINE__;
  2994			goto err_alloc_tcomplete_failed;
  2995		}
  2996		binder_stats_created(BINDER_STAT_TRANSACTION_COMPLETE);
  2997	
  2998		t->debug_id = t_debug_id;
  2999	
  3000		if (reply)
  3001			binder_debug(BINDER_DEBUG_TRANSACTION,
  3002				     "%d:%d BC_REPLY %d -> %d:%d, data %016llx-%016llx size %lld-%lld-%lld\n",
  3003				     proc->pid, thread->pid, t->debug_id,
  3004				     target_proc->pid, target_thread->pid,
  3005				     (u64)tr->data.ptr.buffer,
  3006				     (u64)tr->data.ptr.offsets,
  3007				     (u64)tr->data_size, (u64)tr->offsets_size,
  3008				     (u64)extra_buffers_size);
  3009		else
  3010			binder_debug(BINDER_DEBUG_TRANSACTION,
  3011				     "%d:%d BC_TRANSACTION %d -> %d - node %d, data %016llx-%016llx size %lld-%lld-%lld\n",
  3012				     proc->pid, thread->pid, t->debug_id,
  3013				     target_proc->pid, target_node->debug_id,
  3014				     (u64)tr->data.ptr.buffer,
  3015				     (u64)tr->data.ptr.offsets,
  3016				     (u64)tr->data_size, (u64)tr->offsets_size,
  3017				     (u64)extra_buffers_size);
  3018	
  3019		if (!reply && !(tr->flags & TF_ONE_WAY))
  3020			t->from = thread;
  3021		else
  3022			t->from = NULL;
  3023		t->sender_euid = task_euid(proc->tsk);
  3024		t->to_proc = target_proc;
  3025		t->to_thread = target_thread;
  3026		t->code = tr->code;
  3027		t->flags = tr->flags;
  3028		t->priority = task_nice(current);
  3029	
  3030		if (target_node && target_node->txn_security_ctx) {
  3031			u32 secid;
  3032	
  3033			security_task_getsecid(proc->tsk, &secid);
  3034			ret = security_secid_to_secctx(secid, &secctx, &secctx_sz);
  3035			if (ret) {
  3036				return_error = BR_FAILED_REPLY;
  3037				return_error_param = ret;
  3038				return_error_line = __LINE__;
  3039				goto err_get_secctx_failed;
  3040			}
  3041			extra_buffers_size += ALIGN(secctx_sz, sizeof(u64));
  3042		}
  3043	
  3044		trace_binder_transaction(reply, t, target_node);
  3045	
  3046		t->buffer = binder_alloc_new_buf(&target_proc->alloc, tr->data_size,
  3047			tr->offsets_size, extra_buffers_size,
  3048			!reply && (t->flags & TF_ONE_WAY));
  3049		if (IS_ERR(t->buffer)) {
  3050			/*
  3051			 * -ESRCH indicates VMA cleared. The target is dying.
  3052			 */
  3053			return_error_param = PTR_ERR(t->buffer);
  3054			return_error = return_error_param == -ESRCH ?
  3055				BR_DEAD_REPLY : BR_FAILED_REPLY;
  3056			return_error_line = __LINE__;
  3057			t->buffer = NULL;
  3058			goto err_binder_alloc_buf_failed;
  3059		}
  3060		if (secctx) {
  3061			size_t buf_offset = ALIGN(tr->data_size, sizeof(void *)) +
  3062					    ALIGN(tr->offsets_size, sizeof(void *)) +
  3063					    ALIGN(extra_buffers_size, sizeof(void *)) -
  3064					    ALIGN(secctx_sz, sizeof(u64));
  3065			char *kptr = t->buffer->data + buf_offset;
  3066	
> 3067			t->security_ctx = (binder_uintptr_t)kptr +
  3068			    binder_alloc_get_user_buffer_offset(&target_proc->alloc);
  3069			memcpy(kptr, secctx, secctx_sz);
  3070			security_release_secctx(secctx, secctx_sz);
  3071			secctx = NULL;
  3072		}
  3073		t->buffer->debug_id = t->debug_id;
  3074		t->buffer->transaction = t;
  3075		t->buffer->target_node = target_node;
  3076		trace_binder_transaction_alloc_buf(t->buffer);
  3077		off_start = (binder_size_t *)(t->buffer->data +
  3078					      ALIGN(tr->data_size, sizeof(void *)));
  3079		offp = off_start;
  3080	
  3081		if (copy_from_user(t->buffer->data, (const void __user *)(uintptr_t)
  3082				   tr->data.ptr.buffer, tr->data_size)) {
  3083			binder_user_error("%d:%d got transaction with invalid data ptr\n",
  3084					proc->pid, thread->pid);
  3085			return_error = BR_FAILED_REPLY;
  3086			return_error_param = -EFAULT;
  3087			return_error_line = __LINE__;
  3088			goto err_copy_data_failed;
  3089		}
  3090		if (copy_from_user(offp, (const void __user *)(uintptr_t)
  3091				   tr->data.ptr.offsets, tr->offsets_size)) {
  3092			binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
  3093					proc->pid, thread->pid);
  3094			return_error = BR_FAILED_REPLY;
  3095			return_error_param = -EFAULT;
  3096			return_error_line = __LINE__;
  3097			goto err_copy_data_failed;
  3098		}
  3099		if (!IS_ALIGNED(tr->offsets_size, sizeof(binder_size_t))) {
  3100			binder_user_error("%d:%d got transaction with invalid offsets size, %lld\n",
  3101					proc->pid, thread->pid, (u64)tr->offsets_size);
  3102			return_error = BR_FAILED_REPLY;
  3103			return_error_param = -EINVAL;
  3104			return_error_line = __LINE__;
  3105			goto err_bad_offset;
  3106		}
  3107		if (!IS_ALIGNED(extra_buffers_size, sizeof(u64))) {
  3108			binder_user_error("%d:%d got transaction with unaligned buffers size, %lld\n",
  3109					  proc->pid, thread->pid,
  3110					  (u64)extra_buffers_size);
  3111			return_error = BR_FAILED_REPLY;
  3112			return_error_param = -EINVAL;
  3113			return_error_line = __LINE__;
  3114			goto err_bad_offset;
  3115		}
  3116		off_end = (void *)off_start + tr->offsets_size;
  3117		sg_bufp = (u8 *)(PTR_ALIGN(off_end, sizeof(void *)));
  3118		sg_buf_end = sg_bufp + extra_buffers_size;
  3119		off_min = 0;
  3120		for (; offp < off_end; offp++) {
  3121			struct binder_object_header *hdr;
  3122			size_t object_size = binder_validate_object(t->buffer, *offp);
  3123	
  3124			if (object_size == 0 || *offp < off_min) {
  3125				binder_user_error("%d:%d got transaction with invalid offset (%lld, min %lld max %lld) or object.\n",
  3126						  proc->pid, thread->pid, (u64)*offp,
  3127						  (u64)off_min,
  3128						  (u64)t->buffer->data_size);
  3129				return_error = BR_FAILED_REPLY;
  3130				return_error_param = -EINVAL;
  3131				return_error_line = __LINE__;
  3132				goto err_bad_offset;
  3133			}
  3134	
  3135			hdr = (struct binder_object_header *)(t->buffer->data + *offp);
  3136			off_min = *offp + object_size;
  3137			switch (hdr->type) {
  3138			case BINDER_TYPE_BINDER:
  3139			case BINDER_TYPE_WEAK_BINDER: {
  3140				struct flat_binder_object *fp;
  3141	
  3142				fp = to_flat_binder_object(hdr);
  3143				ret = binder_translate_binder(fp, t, thread);
  3144				if (ret < 0) {
  3145					return_error = BR_FAILED_REPLY;
  3146					return_error_param = ret;
  3147					return_error_line = __LINE__;
  3148					goto err_translate_failed;
  3149				}
  3150			} break;
  3151			case BINDER_TYPE_HANDLE:
  3152			case BINDER_TYPE_WEAK_HANDLE: {
  3153				struct flat_binder_object *fp;
  3154	
  3155				fp = to_flat_binder_object(hdr);
  3156				ret = binder_translate_handle(fp, t, thread);
  3157				if (ret < 0) {
  3158					return_error = BR_FAILED_REPLY;
  3159					return_error_param = ret;
  3160					return_error_line = __LINE__;
  3161					goto err_translate_failed;
  3162				}
  3163			} break;
  3164	
  3165			case BINDER_TYPE_FD: {
  3166				struct binder_fd_object *fp = to_binder_fd_object(hdr);
  3167				int ret = binder_translate_fd(&fp->fd, t, thread,
  3168							      in_reply_to);
  3169	
  3170				if (ret < 0) {
  3171					return_error = BR_FAILED_REPLY;
  3172					return_error_param = ret;
  3173					return_error_line = __LINE__;
  3174					goto err_translate_failed;
  3175				}
  3176				fp->pad_binder = 0;
  3177			} break;
  3178			case BINDER_TYPE_FDA: {
  3179				struct binder_fd_array_object *fda =
  3180					to_binder_fd_array_object(hdr);
  3181				struct binder_buffer_object *parent =
  3182					binder_validate_ptr(t->buffer, fda->parent,
  3183							    off_start,
  3184							    offp - off_start);
  3185				if (!parent) {
  3186					binder_user_error("%d:%d got transaction with invalid parent offset or type\n",
  3187							  proc->pid, thread->pid);
  3188					return_error = BR_FAILED_REPLY;
  3189					return_error_param = -EINVAL;
  3190					return_error_line = __LINE__;
  3191					goto err_bad_parent;
  3192				}
  3193				if (!binder_validate_fixup(t->buffer, off_start,
  3194							   parent, fda->parent_offset,
  3195							   last_fixup_obj,
  3196							   last_fixup_min_off)) {
  3197					binder_user_error("%d:%d got transaction with out-of-order buffer fixup\n",
  3198							  proc->pid, thread->pid);
  3199					return_error = BR_FAILED_REPLY;
  3200					return_error_param = -EINVAL;
  3201					return_error_line = __LINE__;
  3202					goto err_bad_parent;
  3203				}
  3204				ret = binder_translate_fd_array(fda, parent, t, thread,
  3205								in_reply_to);
  3206				if (ret < 0) {
  3207					return_error = BR_FAILED_REPLY;
  3208					return_error_param = ret;
  3209					return_error_line = __LINE__;
  3210					goto err_translate_failed;
  3211				}
  3212				last_fixup_obj = parent;
  3213				last_fixup_min_off =
  3214					fda->parent_offset + sizeof(u32) * fda->num_fds;
  3215			} break;
  3216			case BINDER_TYPE_PTR: {
  3217				struct binder_buffer_object *bp =
  3218					to_binder_buffer_object(hdr);
  3219				size_t buf_left = sg_buf_end - sg_bufp;
  3220	
  3221				if (bp->length > buf_left) {
  3222					binder_user_error("%d:%d got transaction with too large buffer\n",
  3223							  proc->pid, thread->pid);
  3224					return_error = BR_FAILED_REPLY;
  3225					return_error_param = -EINVAL;
  3226					return_error_line = __LINE__;
  3227					goto err_bad_offset;
  3228				}
  3229				if (copy_from_user(sg_bufp,
  3230						   (const void __user *)(uintptr_t)
  3231						   bp->buffer, bp->length)) {
  3232					binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
  3233							  proc->pid, thread->pid);
  3234					return_error_param = -EFAULT;
  3235					return_error = BR_FAILED_REPLY;
  3236					return_error_line = __LINE__;
  3237					goto err_copy_data_failed;
  3238				}
  3239				/* Fixup buffer pointer to target proc address space */
  3240				bp->buffer = (uintptr_t)sg_bufp +
  3241					binder_alloc_get_user_buffer_offset(
  3242							&target_proc->alloc);
  3243				sg_bufp += ALIGN(bp->length, sizeof(u64));
  3244	
  3245				ret = binder_fixup_parent(t, thread, bp, off_start,
  3246							  offp - off_start,
  3247							  last_fixup_obj,
  3248							  last_fixup_min_off);
  3249				if (ret < 0) {
  3250					return_error = BR_FAILED_REPLY;
  3251					return_error_param = ret;
  3252					return_error_line = __LINE__;
  3253					goto err_translate_failed;
  3254				}
  3255				last_fixup_obj = bp;
  3256				last_fixup_min_off = 0;
  3257			} break;
  3258			default:
  3259				binder_user_error("%d:%d got transaction with invalid object type, %x\n",
  3260					proc->pid, thread->pid, hdr->type);
  3261				return_error = BR_FAILED_REPLY;
  3262				return_error_param = -EINVAL;
  3263				return_error_line = __LINE__;
  3264				goto err_bad_object_type;
  3265			}
  3266		}
  3267		tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
  3268		t->work.type = BINDER_WORK_TRANSACTION;
  3269	
  3270		if (reply) {
  3271			binder_enqueue_thread_work(thread, tcomplete);
  3272			binder_inner_proc_lock(target_proc);
  3273			if (target_thread->is_dead) {
  3274				binder_inner_proc_unlock(target_proc);
  3275				goto err_dead_proc_or_thread;
  3276			}
  3277			BUG_ON(t->buffer->async_transaction != 0);
  3278			binder_pop_transaction_ilocked(target_thread, in_reply_to);
  3279			binder_enqueue_thread_work_ilocked(target_thread, &t->work);
  3280			binder_inner_proc_unlock(target_proc);
  3281			wake_up_interruptible_sync(&target_thread->wait);
  3282			binder_free_transaction(in_reply_to);
  3283		} else if (!(t->flags & TF_ONE_WAY)) {
  3284			BUG_ON(t->buffer->async_transaction != 0);
  3285			binder_inner_proc_lock(proc);
  3286			/*
  3287			 * Defer the TRANSACTION_COMPLETE, so we don't return to
  3288			 * userspace immediately; this allows the target process to
  3289			 * immediately start processing this transaction, reducing
  3290			 * latency. We will then return the TRANSACTION_COMPLETE when
  3291			 * the target replies (or there is an error).
  3292			 */
  3293			binder_enqueue_deferred_thread_work_ilocked(thread, tcomplete);
  3294			t->need_reply = 1;
  3295			t->from_parent = thread->transaction_stack;
  3296			thread->transaction_stack = t;
  3297			binder_inner_proc_unlock(proc);
  3298			if (!binder_proc_transaction(t, target_proc, target_thread)) {
  3299				binder_inner_proc_lock(proc);
  3300				binder_pop_transaction_ilocked(thread, t);
  3301				binder_inner_proc_unlock(proc);
  3302				goto err_dead_proc_or_thread;
  3303			}
  3304		} else {
  3305			BUG_ON(target_node == NULL);
  3306			BUG_ON(t->buffer->async_transaction != 1);
  3307			binder_enqueue_thread_work(thread, tcomplete);
  3308			if (!binder_proc_transaction(t, target_proc, NULL))
  3309				goto err_dead_proc_or_thread;
  3310		}
  3311		if (target_thread)
  3312			binder_thread_dec_tmpref(target_thread);
  3313		binder_proc_dec_tmpref(target_proc);
  3314		if (target_node)
  3315			binder_dec_node_tmpref(target_node);
  3316		/*
  3317		 * write barrier to synchronize with initialization
  3318		 * of log entry
  3319		 */
  3320		smp_wmb();
  3321		WRITE_ONCE(e->debug_id_done, t_debug_id);
  3322		return;
  3323	
  3324	err_dead_proc_or_thread:
  3325		return_error = BR_DEAD_REPLY;
  3326		return_error_line = __LINE__;
  3327		binder_dequeue_work(proc, tcomplete);
  3328	err_translate_failed:
  3329	err_bad_object_type:
  3330	err_bad_offset:
  3331	err_bad_parent:
  3332	err_copy_data_failed:
  3333		binder_free_txn_fixups(t);
  3334		trace_binder_transaction_failed_buffer_release(t->buffer);
  3335		binder_transaction_buffer_release(target_proc, t->buffer, offp);
  3336		if (target_node)
  3337			binder_dec_node_tmpref(target_node);
  3338		target_node = NULL;
  3339		t->buffer->transaction = NULL;
  3340		binder_alloc_free_buf(&target_proc->alloc, t->buffer);
  3341	err_binder_alloc_buf_failed:
  3342		if (secctx)
  3343			security_release_secctx(secctx, secctx_sz);
  3344	err_get_secctx_failed:
  3345		kfree(tcomplete);
  3346		binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
  3347	err_alloc_tcomplete_failed:
  3348		kfree(t);
  3349		binder_stats_deleted(BINDER_STAT_TRANSACTION);
  3350	err_alloc_t_failed:
  3351	err_bad_todo_list:
  3352	err_bad_call_stack:
  3353	err_empty_call_stack:
  3354	err_dead_binder:
  3355	err_invalid_target_handle:
  3356		if (target_thread)
  3357			binder_thread_dec_tmpref(target_thread);
  3358		if (target_proc)
  3359			binder_proc_dec_tmpref(target_proc);
  3360		if (target_node) {
  3361			binder_dec_node(target_node, 1, 0);
  3362			binder_dec_node_tmpref(target_node);
  3363		}
  3364	
  3365		binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
  3366			     "%d:%d transaction failed %d/%d, size %lld-%lld line %d\n",
  3367			     proc->pid, thread->pid, return_error, return_error_param,
  3368			     (u64)tr->data_size, (u64)tr->offsets_size,
  3369			     return_error_line);
  3370	
  3371		{
  3372			struct binder_transaction_log_entry *fe;
  3373	
  3374			e->return_error = return_error;
  3375			e->return_error_param = return_error_param;
  3376			e->return_error_line = return_error_line;
  3377			fe = binder_transaction_log_add(&binder_transaction_log_failed);
  3378			*fe = *e;
  3379			/*
  3380			 * write barrier to synchronize with initialization
  3381			 * of log entry
  3382			 */
  3383			smp_wmb();
  3384			WRITE_ONCE(e->debug_id_done, t_debug_id);
  3385			WRITE_ONCE(fe->debug_id_done, t_debug_id);
  3386		}
  3387	
  3388		BUG_ON(thread->return_error.cmd != BR_OK);
  3389		if (in_reply_to) {
  3390			thread->return_error.cmd = BR_TRANSACTION_COMPLETE;
  3391			binder_enqueue_thread_work(thread, &thread->return_error.work);
  3392			binder_send_failed_reply(in_reply_to, return_error);
  3393		} else {
  3394			thread->return_error.cmd = return_error;
  3395			binder_enqueue_thread_work(thread, &thread->return_error.work);
  3396		}
  3397	}
  3398	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

Download attachment ".config.gz" of type "application/gzip" (34379 bytes)

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ