diff mbox series

[v33,13/29] LSM: Use lsmblob in security_cred_getsecid

Message ID 20220310234632.16194-14-casey@schaufler-ca.com (mailing list archive)
State New, archived
Headers show
Series None | expand

Commit Message

Casey Schaufler March 10, 2022, 11:46 p.m. UTC
Change the security_cred_getsecid() interface to fill in a
lsmblob instead of a u32 secid. The associated data elements
in the audit sub-system are changed from a secid to a lsmblob
to accommodate multiple possible LSM audit users.

Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: John Johansen <john.johansen@canonical.com>
Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Acked-by: Paul Moore <paul@paul-moore.com>
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Cc: linux-integrity@vger.kernel.org
Cc: linux-audit@redhat.com
---
 drivers/android/binder.c          | 12 +----------
 include/linux/security.h          |  2 +-
 kernel/audit.c                    | 25 +++++++----------------
 kernel/audit.h                    |  3 ++-
 kernel/auditsc.c                  | 33 +++++++++++--------------------
 security/integrity/ima/ima_main.c |  8 ++++----
 security/security.c               | 12 ++++++++---
 7 files changed, 36 insertions(+), 59 deletions(-)

Comments

kernel test robot March 11, 2022, 7:52 a.m. UTC | #1
Hi Casey,

I love your patch! Yet something to improve:

[auto build test ERROR on pcmoore-audit/next]
[also build test ERROR on linus/master v5.17-rc7]
[cannot apply to pcmoore-selinux/next jmorris-security/next-testing next-20220310]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Casey-Schaufler/integrity-disassociate-ima_filter_rule-from-security_audit_rule/20220311-084644
base:   https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit.git next
config: arc-randconfig-r043-20220310 (https://download.01.org/0day-ci/archive/20220311/202203111533.VLOzBETK-lkp@intel.com/config)
compiler: arceb-elf-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/77c3979bacdff1630a3c6211db065f2c79412621
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Casey-Schaufler/integrity-disassociate-ima_filter_rule-from-security_audit_rule/20220311-084644
        git checkout 77c3979bacdff1630a3c6211db065f2c79412621
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=arc SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   drivers/android/binder.c: In function 'binder_transaction':
>> drivers/android/binder.c:2986:52: error: passing argument 2 of 'security_cred_getsecid' from incompatible pointer type [-Werror=incompatible-pointer-types]
    2986 |                 security_cred_getsecid(proc->cred, &blob);
         |                                                    ^~~~~
         |                                                    |
         |                                                    struct lsmblob *
   In file included from drivers/android/binder.c:63:
   include/linux/security.h:1126:70: note: expected 'u32 *' {aka 'unsigned int *'} but argument is of type 'struct lsmblob *'
    1126 | static inline void security_cred_getsecid(const struct cred *c, u32 *secid)
         |                                                                 ~~~~~^~~~~
   cc1: some warnings being treated as errors


vim +/security_cred_getsecid +2986 drivers/android/binder.c

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

---
0-DAY CI Kernel Test Service
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
kernel test robot March 11, 2022, 9:16 a.m. UTC | #2
Hi Casey,

I love your patch! Yet something to improve:

[auto build test ERROR on pcmoore-audit/next]
[also build test ERROR on linus/master v5.17-rc7]
[cannot apply to pcmoore-selinux/next jmorris-security/next-testing next-20220310]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Casey-Schaufler/integrity-disassociate-ima_filter_rule-from-security_audit_rule/20220311-084644
base:   https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit.git next
config: hexagon-randconfig-r041-20220310 (https://download.01.org/0day-ci/archive/20220311/202203111731.kM4VVdt5-lkp@intel.com/config)
compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project 276ca87382b8f16a65bddac700202924228982f6)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/77c3979bacdff1630a3c6211db065f2c79412621
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Casey-Schaufler/integrity-disassociate-ima_filter_rule-from-security_audit_rule/20220311-084644
        git checkout 77c3979bacdff1630a3c6211db065f2c79412621
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash drivers/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> drivers/android/binder.c:2986:38: error: incompatible pointer types passing 'struct lsmblob *' to parameter of type 'u32 *' (aka 'unsigned int *') [-Werror,-Wincompatible-pointer-types]
                   security_cred_getsecid(proc->cred, &blob);
                                                      ^~~~~
   include/linux/security.h:1126:70: note: passing argument to parameter 'secid' here
   static inline void security_cred_getsecid(const struct cred *c, u32 *secid)
                                                                        ^
   1 error generated.


vim +2986 drivers/android/binder.c

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

---
0-DAY CI Kernel Test Service
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
kernel test robot March 12, 2022, 4:50 a.m. UTC | #3
Hi Casey,

I love your patch! Perhaps something to improve:

[auto build test WARNING on pcmoore-audit/next]
[also build test WARNING on linus/master v5.17-rc7]
[cannot apply to pcmoore-selinux/next jmorris-security/next-testing next-20220310]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Casey-Schaufler/integrity-disassociate-ima_filter_rule-from-security_audit_rule/20220311-084644
base:   https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit.git next
config: microblaze-randconfig-s031-20220310 (https://download.01.org/0day-ci/archive/20220312/202203121225.Ab2lmSD3-lkp@intel.com/config)
compiler: microblaze-linux-gcc (GCC) 11.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # apt-get install sparse
        # sparse version: v0.6.4-dirty
        # https://github.com/0day-ci/linux/commit/77c3979bacdff1630a3c6211db065f2c79412621
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Casey-Schaufler/integrity-disassociate-ima_filter_rule-from-security_audit_rule/20220311-084644
        git checkout 77c3979bacdff1630a3c6211db065f2c79412621
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=microblaze SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


sparse warnings: (new ones prefixed by >>)
>> kernel/audit.c:128:25: sparse: sparse: symbol 'audit_sig_lsm' was not declared. Should it be static?
   kernel/audit.c:2197:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/audit.c:2197:9: sparse:     expected struct spinlock [usertype] *lock
   kernel/audit.c:2197:9: sparse:     got struct spinlock [noderef] __rcu *
   kernel/audit.c:2200:40: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected struct spinlock [usertype] *lock @@     got struct spinlock [noderef] __rcu * @@
   kernel/audit.c:2200:40: sparse:     expected struct spinlock [usertype] *lock
   kernel/audit.c:2200:40: sparse:     got struct spinlock [noderef] __rcu *

vim +/audit_sig_lsm +128 kernel/audit.c

   124	
   125	/* The identity of the user shutting down the audit system. */
   126	static kuid_t		audit_sig_uid = INVALID_UID;
   127	static pid_t		audit_sig_pid = -1;
 > 128	struct lsmblob		audit_sig_lsm;
   129	

---
0-DAY CI Kernel Test Service
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff mbox series

Patch

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index bae8440ffc73..26838061defb 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2982,18 +2982,8 @@  static void binder_transaction(struct binder_proc *proc,
 	if (target_node && target_node->txn_security_ctx) {
 		struct lsmblob blob;
 		size_t added_size;
-		u32 secid;
 
-		security_cred_getsecid(proc->cred, &secid);
-		/*
-		 * Later in this patch set security_cred_getsecid() will
-		 * provide a lsmblob instead of a secid. lsmblob_init
-		 * is used to ensure that all the secids in the lsmblob
-		 * get the value returned from security_cred_getsecid(),
-		 * which means that the one expected by
-		 * security_secid_to_secctx() will be set.
-		 */
-		lsmblob_init(&blob, secid);
+		security_cred_getsecid(proc->cred, &blob);
 		ret = security_secid_to_secctx(&blob, &secctx, &secctx_sz);
 		if (ret) {
 			return_error = BR_FAILED_REPLY;
diff --git a/include/linux/security.h b/include/linux/security.h
index 6fc573d2c253..955f75fc1007 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -483,7 +483,7 @@  int security_cred_alloc_blank(struct cred *cred, gfp_t gfp);
 void security_cred_free(struct cred *cred);
 int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp);
 void security_transfer_creds(struct cred *new, const struct cred *old);
-void security_cred_getsecid(const struct cred *c, u32 *secid);
+void security_cred_getsecid(const struct cred *c, struct lsmblob *blob);
 int security_kernel_act_as(struct cred *new, struct lsmblob *blob);
 int security_kernel_create_files_as(struct cred *new, struct inode *inode);
 int security_kernel_module_request(char *kmod_name);
diff --git a/kernel/audit.c b/kernel/audit.c
index 17ac6e74b5bd..c7cd039e258b 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -125,7 +125,7 @@  static u32	audit_backlog_wait_time = AUDIT_BACKLOG_WAIT_TIME;
 /* The identity of the user shutting down the audit system. */
 static kuid_t		audit_sig_uid = INVALID_UID;
 static pid_t		audit_sig_pid = -1;
-static u32		audit_sig_sid;
+struct lsmblob		audit_sig_lsm;
 
 /* Records can be lost in several ways:
    0) [suppressed in audit_alloc]
@@ -1439,29 +1439,21 @@  static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 	}
 	case AUDIT_SIGNAL_INFO:
 		len = 0;
-		if (audit_sig_sid) {
-			struct lsmblob blob;
-
-			/*
-			 * lsmblob_init sets all values in the lsmblob
-			 * to audit_sig_sid. This is temporary until
-			 * audit_sig_sid is converted to a lsmblob, which
-			 * happens later in this patch set.
-			 */
-			lsmblob_init(&blob, audit_sig_sid);
-			err = security_secid_to_secctx(&blob, &ctx, &len);
+		if (lsmblob_is_set(&audit_sig_lsm)) {
+			err = security_secid_to_secctx(&audit_sig_lsm, &ctx,
+						       &len);
 			if (err)
 				return err;
 		}
 		sig_data = kmalloc(struct_size(sig_data, ctx, len), GFP_KERNEL);
 		if (!sig_data) {
-			if (audit_sig_sid)
+			if (lsmblob_is_set(&audit_sig_lsm))
 				security_release_secctx(ctx, len);
 			return -ENOMEM;
 		}
 		sig_data->uid = from_kuid(&init_user_ns, audit_sig_uid);
 		sig_data->pid = audit_sig_pid;
-		if (audit_sig_sid) {
+		if (lsmblob_is_set(&audit_sig_lsm)) {
 			memcpy(sig_data->ctx, ctx, len);
 			security_release_secctx(ctx, len);
 		}
@@ -2368,7 +2360,6 @@  int audit_set_loginuid(kuid_t loginuid)
 int audit_signal_info(int sig, struct task_struct *t)
 {
 	kuid_t uid = current_uid(), auid;
-	struct lsmblob blob;
 
 	if (auditd_test_task(t) &&
 	    (sig == SIGTERM || sig == SIGHUP ||
@@ -2379,9 +2370,7 @@  int audit_signal_info(int sig, struct task_struct *t)
 			audit_sig_uid = auid;
 		else
 			audit_sig_uid = uid;
-		security_current_getsecid_subj(&blob);
-		/* scaffolding until audit_sig_sid is converted */
-		audit_sig_sid = blob.secid[0];
+		security_current_getsecid_subj(&audit_sig_lsm);
 	}
 
 	return audit_signal_info_syscall(t);
diff --git a/kernel/audit.h b/kernel/audit.h
index c4498090a5bd..527d4c4acb12 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -12,6 +12,7 @@ 
 #include <linux/fs.h>
 #include <linux/audit.h>
 #include <linux/skbuff.h>
+#include <linux/security.h>
 #include <uapi/linux/mqueue.h>
 #include <linux/tty.h>
 #include <uapi/linux/openat2.h> // struct open_how
@@ -143,7 +144,7 @@  struct audit_context {
 	kuid_t		    target_auid;
 	kuid_t		    target_uid;
 	unsigned int	    target_sessionid;
-	u32		    target_sid;
+	struct lsmblob	    target_lsm;
 	char		    target_comm[TASK_COMM_LEN];
 
 	struct audit_tree_refs *trees, *first_trees;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 6cd15abb99c7..c4c3666576c3 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -99,7 +99,7 @@  struct audit_aux_data_pids {
 	kuid_t			target_auid[AUDIT_AUX_PIDS];
 	kuid_t			target_uid[AUDIT_AUX_PIDS];
 	unsigned int		target_sessionid[AUDIT_AUX_PIDS];
-	u32			target_sid[AUDIT_AUX_PIDS];
+	struct lsmblob		target_lsm[AUDIT_AUX_PIDS];
 	char 			target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN];
 	int			pid_count;
 };
@@ -1018,7 +1018,7 @@  static void audit_reset_context(struct audit_context *ctx)
 	ctx->target_pid = 0;
 	ctx->target_auid = ctx->target_uid = KUIDT_INIT(0);
 	ctx->target_sessionid = 0;
-	ctx->target_sid = 0;
+	lsmblob_init(&ctx->target_lsm, 0);
 	ctx->target_comm[0] = '\0';
 	unroll_tree_refs(ctx, NULL, 0);
 	WARN_ON(!list_empty(&ctx->killed_trees));
@@ -1116,14 +1116,14 @@  static inline void audit_free_context(struct audit_context *context)
 }
 
 static int audit_log_pid_context(struct audit_context *context, pid_t pid,
-				 kuid_t auid, kuid_t uid, unsigned int sessionid,
-				 u32 sid, char *comm)
+				 kuid_t auid, kuid_t uid,
+				 unsigned int sessionid,
+				 struct lsmblob *blob, char *comm)
 {
 	struct audit_buffer *ab;
 	char *ctx = NULL;
 	u32 len;
 	int rc = 0;
-	struct lsmblob blob;
 
 	ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
 	if (!ab)
@@ -1132,9 +1132,8 @@  static int audit_log_pid_context(struct audit_context *context, pid_t pid,
 	audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid,
 			 from_kuid(&init_user_ns, auid),
 			 from_kuid(&init_user_ns, uid), sessionid);
-	if (sid) {
-		lsmblob_init(&blob, sid);
-		if (security_secid_to_secctx(&blob, &ctx, &len)) {
+	if (lsmblob_is_set(blob)) {
+		if (security_secid_to_secctx(blob, &ctx, &len)) {
 			audit_log_format(ab, " obj=(none)");
 			rc = 1;
 		} else {
@@ -1762,7 +1761,7 @@  static void audit_log_exit(void)
 						  axs->target_auid[i],
 						  axs->target_uid[i],
 						  axs->target_sessionid[i],
-						  axs->target_sid[i],
+						  &axs->target_lsm[i],
 						  axs->target_comm[i]))
 				call_panic = 1;
 	}
@@ -1771,7 +1770,7 @@  static void audit_log_exit(void)
 	    audit_log_pid_context(context, context->target_pid,
 				  context->target_auid, context->target_uid,
 				  context->target_sessionid,
-				  context->target_sid, context->target_comm))
+				  &context->target_lsm, context->target_comm))
 			call_panic = 1;
 
 	if (context->pwd.dentry && context->pwd.mnt) {
@@ -2707,15 +2706,12 @@  int __audit_sockaddr(int len, void *a)
 void __audit_ptrace(struct task_struct *t)
 {
 	struct audit_context *context = audit_context();
-	struct lsmblob blob;
 
 	context->target_pid = task_tgid_nr(t);
 	context->target_auid = audit_get_loginuid(t);
 	context->target_uid = task_uid(t);
 	context->target_sessionid = audit_get_sessionid(t);
-	security_task_getsecid_obj(t, &blob);
-	/* scaffolding - until target_sid is converted */
-	context->target_sid = blob.secid[0];
+	security_task_getsecid_obj(t, &context->target_lsm);
 	memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
 }
 
@@ -2731,7 +2727,6 @@  int audit_signal_info_syscall(struct task_struct *t)
 	struct audit_aux_data_pids *axp;
 	struct audit_context *ctx = audit_context();
 	kuid_t t_uid = task_uid(t);
-	struct lsmblob blob;
 
 	if (!audit_signals || audit_dummy_context())
 		return 0;
@@ -2743,9 +2738,7 @@  int audit_signal_info_syscall(struct task_struct *t)
 		ctx->target_auid = audit_get_loginuid(t);
 		ctx->target_uid = t_uid;
 		ctx->target_sessionid = audit_get_sessionid(t);
-		security_task_getsecid_obj(t, &blob);
-		/* scaffolding until target_sid is converted */
-		ctx->target_sid = blob.secid[0];
+		security_task_getsecid_obj(t, &ctx->target_lsm);
 		memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
 		return 0;
 	}
@@ -2766,9 +2759,7 @@  int audit_signal_info_syscall(struct task_struct *t)
 	axp->target_auid[axp->pid_count] = audit_get_loginuid(t);
 	axp->target_uid[axp->pid_count] = t_uid;
 	axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
-	security_task_getsecid_obj(t, &blob);
-	/* scaffolding until target_sid is converted */
-	axp->target_sid[axp->pid_count] = blob.secid[0];
+	security_task_getsecid_obj(t, &axp->target_lsm[axp->pid_count]);
 	memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
 	axp->pid_count++;
 
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 6abbaa97bbeb..93c6addd8389 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -486,7 +486,6 @@  int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot)
 int ima_bprm_check(struct linux_binprm *bprm)
 {
 	int ret;
-	u32 secid;
 	struct lsmblob blob;
 
 	security_current_getsecid_subj(&blob);
@@ -496,9 +495,10 @@  int ima_bprm_check(struct linux_binprm *bprm)
 	if (ret)
 		return ret;
 
-	security_cred_getsecid(bprm->cred, &secid);
-	return process_measurement(bprm->file, bprm->cred, secid, NULL, 0,
-				   MAY_EXEC, CREDS_CHECK);
+	security_cred_getsecid(bprm->cred, &blob);
+	/* scaffolding until process_measurement changes */
+	return process_measurement(bprm->file, bprm->cred, blob.secid[0],
+				   NULL, 0, MAY_EXEC, CREDS_CHECK);
 }
 
 /**
diff --git a/security/security.c b/security/security.c
index 0253c925a272..27154c39d109 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1803,10 +1803,16 @@  void security_transfer_creds(struct cred *new, const struct cred *old)
 	call_void_hook(cred_transfer, new, old);
 }
 
-void security_cred_getsecid(const struct cred *c, u32 *secid)
+void security_cred_getsecid(const struct cred *c, struct lsmblob *blob)
 {
-	*secid = 0;
-	call_void_hook(cred_getsecid, c, secid);
+	struct security_hook_list *hp;
+
+	lsmblob_init(blob, 0);
+	hlist_for_each_entry(hp, &security_hook_heads.cred_getsecid, list) {
+		if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
+			continue;
+		hp->hook.cred_getsecid(c, &blob->secid[hp->lsmid->slot]);
+	}
 }
 EXPORT_SYMBOL(security_cred_getsecid);