2022-03-11 22:51:34

by Casey Schaufler

[permalink] [raw]
Subject: [PATCH v33 13/29] LSM: Use lsmblob in security_cred_getsecid

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 <[email protected]>
Reviewed-by: John Johansen <[email protected]>
Acked-by: Stephen Smalley <[email protected]>
Acked-by: Paul Moore <[email protected]>
Signed-off-by: Casey Schaufler <[email protected]>
Cc: [email protected]
Cc: [email protected]
---
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(-)

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);

--
2.31.1


2022-03-11 23:12:14

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v33 13/29] LSM: Use lsmblob in security_cred_getsecid

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/[email protected]/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 <[email protected]>

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/[email protected]

2022-03-11 23:16:20

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v33 13/29] LSM: Use lsmblob in security_cred_getsecid

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/[email protected]/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 <[email protected]>

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/[email protected]

2022-03-12 08:35:48

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v33 13/29] LSM: Use lsmblob in security_cred_getsecid

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/[email protected]/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 <[email protected]>


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/[email protected]