* [PATCH v33 11/29] LSM: Use lsmblob in security_current_getsecid
[not found] <20220310234632.16194-1-casey@schaufler-ca.com>
@ 2022-03-10 23:46 ` Casey Schaufler
2022-03-10 23:46 ` [PATCH v33 12/29] LSM: Use lsmblob in security_inode_getsecid Casey Schaufler
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: Casey Schaufler @ 2022-03-10 23:46 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux
Cc: casey, linux-audit, keescook, john.johansen, penguin-kernel, paul,
stephen.smalley.work, linux-kernel, linux-integrity, netdev
Change the security_current_getsecid_subj() and
security_task_getsecid_obj() interfaces to fill in
a lsmblob structure instead of a u32 secid in support of
LSM stacking. Audit interfaces will need to collect all
possible secids for possible reporting.
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
Cc: netdev@vger.kernel.org
---
drivers/android/binder.c | 6 +--
include/linux/security.h | 13 ++++---
kernel/audit.c | 16 +++-----
kernel/auditfilter.c | 4 +-
kernel/auditsc.c | 25 ++++++------
net/netlabel/netlabel_unlabeled.c | 5 ++-
net/netlabel/netlabel_user.h | 6 ++-
security/integrity/ima/ima_appraise.c | 12 +++---
security/integrity/ima/ima_main.c | 55 +++++++++++++++------------
security/security.c | 25 +++++++++---
10 files changed, 95 insertions(+), 72 deletions(-)
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 381a4fddd4a5..bae8440ffc73 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2980,16 +2980,16 @@ static void binder_transaction(struct binder_proc *proc,
t->priority = task_nice(current);
if (target_node && target_node->txn_security_ctx) {
- u32 secid;
struct lsmblob blob;
size_t added_size;
+ u32 secid;
security_cred_getsecid(proc->cred, &secid);
/*
- * Later in this patch set security_task_getsecid() will
+ * 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_task_getsecid(),
+ * get the value returned from security_cred_getsecid(),
* which means that the one expected by
* security_secid_to_secctx() will be set.
*/
diff --git a/include/linux/security.h b/include/linux/security.h
index 1814516509ec..5f20c0c68f67 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -502,8 +502,8 @@ int security_task_fix_setgid(struct cred *new, const struct cred *old,
int security_task_setpgid(struct task_struct *p, pid_t pgid);
int security_task_getpgid(struct task_struct *p);
int security_task_getsid(struct task_struct *p);
-void security_current_getsecid_subj(u32 *secid);
-void security_task_getsecid_obj(struct task_struct *p, u32 *secid);
+void security_current_getsecid_subj(struct lsmblob *blob);
+void security_task_getsecid_obj(struct task_struct *p, struct lsmblob *blob);
int security_task_setnice(struct task_struct *p, int nice);
int security_task_setioprio(struct task_struct *p, int ioprio);
int security_task_getioprio(struct task_struct *p);
@@ -1199,14 +1199,15 @@ static inline int security_task_getsid(struct task_struct *p)
return 0;
}
-static inline void security_current_getsecid_subj(u32 *secid)
+static inline void security_current_getsecid_subj(struct lsmblob *blob)
{
- *secid = 0;
+ lsmblob_init(blob, 0);
}
-static inline void security_task_getsecid_obj(struct task_struct *p, u32 *secid)
+static inline void security_task_getsecid_obj(struct task_struct *p,
+ struct lsmblob *blob)
{
- *secid = 0;
+ lsmblob_init(blob, 0);
}
static inline int security_task_setnice(struct task_struct *p, int nice)
diff --git a/kernel/audit.c b/kernel/audit.c
index 40d8cb824eae..17ac6e74b5bd 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -2154,19 +2154,12 @@ int audit_log_task_context(struct audit_buffer *ab)
char *ctx = NULL;
unsigned len;
int error;
- u32 sid;
struct lsmblob blob;
- security_current_getsecid_subj(&sid);
- if (!sid)
+ security_current_getsecid_subj(&blob);
+ if (!lsmblob_is_set(&blob))
return 0;
- /*
- * lsmblob_init sets all values in the lsmblob to sid.
- * This is temporary until security_task_getsecid is converted
- * to use a lsmblob, which happens later in this patch set.
- */
- lsmblob_init(&blob, sid);
error = security_secid_to_secctx(&blob, &ctx, &len);
if (error) {
@@ -2375,6 +2368,7 @@ 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 ||
@@ -2385,7 +2379,9 @@ int audit_signal_info(int sig, struct task_struct *t)
audit_sig_uid = auid;
else
audit_sig_uid = uid;
- security_current_getsecid_subj(&audit_sig_sid);
+ security_current_getsecid_subj(&blob);
+ /* scaffolding until audit_sig_sid is converted */
+ audit_sig_sid = blob.secid[0];
}
return audit_signal_info_syscall(t);
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 15cd4fe35e9c..39ded5cb2429 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -1339,7 +1339,6 @@ int audit_filter(int msgtype, unsigned int listtype)
struct audit_field *f = &e->rule.fields[i];
struct lsmblob blob;
pid_t pid;
- u32 sid;
switch (f->type) {
case AUDIT_PID:
@@ -1369,8 +1368,7 @@ int audit_filter(int msgtype, unsigned int listtype)
case AUDIT_SUBJ_SEN:
case AUDIT_SUBJ_CLR:
if (f->lsm_str) {
- security_current_getsecid_subj(&sid);
- lsmblob_init(&blob, sid);
+ security_current_getsecid_subj(&blob);
result = security_audit_rule_match(
&blob, f->type, f->op,
&f->lsm_rules);
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 598e0de45b04..2570bf5979e0 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -467,7 +467,6 @@ static int audit_filter_rules(struct task_struct *tsk,
{
const struct cred *cred;
int i, need_sid = 1;
- u32 sid;
struct lsmblob blob;
unsigned int sessionid;
@@ -676,17 +675,9 @@ static int audit_filter_rules(struct task_struct *tsk,
* here even though it always refs
* @current's creds
*/
- security_current_getsecid_subj(&sid);
+ security_current_getsecid_subj(&blob);
need_sid = 0;
}
- /*
- * lsmblob_init sets all values in the lsmblob
- * to sid. This is temporary until
- * security_task_getsecid() is converted to
- * provide a lsmblob, which happens later in
- * this patch set.
- */
- lsmblob_init(&blob, sid);
result = security_audit_rule_match(&blob,
f->type, f->op,
&f->lsm_rules);
@@ -2712,12 +2703,15 @@ 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, &context->target_sid);
+ security_task_getsecid_obj(t, &blob);
+ /* scaffolding - until target_sid is converted */
+ context->target_sid = blob.secid[0];
memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
}
@@ -2733,6 +2727,7 @@ 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;
@@ -2744,7 +2739,9 @@ 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, &ctx->target_sid);
+ security_task_getsecid_obj(t, &blob);
+ /* scaffolding until target_sid is converted */
+ ctx->target_sid = blob.secid[0];
memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
return 0;
}
@@ -2765,7 +2762,9 @@ 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, &axp->target_sid[axp->pid_count]);
+ security_task_getsecid_obj(t, &blob);
+ /* scaffolding until target_sid is converted */
+ axp->target_sid[axp->pid_count] = blob.secid[0];
memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
axp->pid_count++;
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 0a99663e6edb..c86df6ead742 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -1562,11 +1562,14 @@ int __init netlbl_unlabel_defconf(void)
int ret_val;
struct netlbl_dom_map *entry;
struct netlbl_audit audit_info;
+ struct lsmblob blob;
/* Only the kernel is allowed to call this function and the only time
* it is called is at bootup before the audit subsystem is reporting
* messages so don't worry to much about these values. */
- security_current_getsecid_subj(&audit_info.secid);
+ security_current_getsecid_subj(&blob);
+ /* scaffolding until audit_info.secid is converted */
+ audit_info.secid = blob.secid[0];
audit_info.loginuid = GLOBAL_ROOT_UID;
audit_info.sessionid = 0;
diff --git a/net/netlabel/netlabel_user.h b/net/netlabel/netlabel_user.h
index d6c5b31eb4eb..3d5610ed5f0e 100644
--- a/net/netlabel/netlabel_user.h
+++ b/net/netlabel/netlabel_user.h
@@ -32,7 +32,11 @@
*/
static inline void netlbl_netlink_auditinfo(struct netlbl_audit *audit_info)
{
- security_current_getsecid_subj(&audit_info->secid);
+ struct lsmblob blob;
+
+ security_current_getsecid_subj(&blob);
+ /* scaffolding until secid is converted */
+ audit_info->secid = blob.secid[0];
audit_info->loginuid = audit_get_loginuid(current);
audit_info->sessionid = audit_get_sessionid(current);
}
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 17232bbfb9f9..217d20c60e1d 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -71,15 +71,17 @@ bool is_ima_appraise_enabled(void)
int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode,
int mask, enum ima_hooks func)
{
- u32 secid;
+ struct lsmblob blob;
if (!ima_appraise)
return 0;
- security_current_getsecid_subj(&secid);
- return ima_match_policy(mnt_userns, inode, current_cred(), secid,
- func, mask, IMA_APPRAISE | IMA_HASH, NULL,
- NULL, NULL, NULL);
+ security_current_getsecid_subj(&blob);
+ /* scaffolding the .secid[0] */
+ return ima_match_policy(mnt_userns, inode, current_cred(),
+ blob.secid[0], func, mask,
+ IMA_APPRAISE | IMA_HASH, NULL, NULL, NULL,
+ NULL);
}
static int ima_fix_xattr(struct dentry *dentry,
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 8c6e4514d494..6abbaa97bbeb 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -405,12 +405,13 @@ static int process_measurement(struct file *file, const struct cred *cred,
*/
int ima_file_mmap(struct file *file, unsigned long prot)
{
- u32 secid;
+ struct lsmblob blob;
if (file && (prot & PROT_EXEC)) {
- security_current_getsecid_subj(&secid);
- return process_measurement(file, current_cred(), secid, NULL,
- 0, MAY_EXEC, MMAP_CHECK);
+ security_current_getsecid_subj(&blob);
+ /* scaffolding - until process_measurement changes */
+ return process_measurement(file, current_cred(), blob.secid[0],
+ NULL, 0, MAY_EXEC, MMAP_CHECK);
}
return 0;
@@ -436,9 +437,9 @@ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot)
char *pathbuf = NULL;
const char *pathname = NULL;
struct inode *inode;
+ struct lsmblob blob;
int result = 0;
int action;
- u32 secid;
int pcr;
/* Is mprotect making an mmap'ed file executable? */
@@ -446,11 +447,11 @@ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot)
!(prot & PROT_EXEC) || (vma->vm_flags & VM_EXEC))
return 0;
- security_current_getsecid_subj(&secid);
+ security_current_getsecid_subj(&blob);
inode = file_inode(vma->vm_file);
action = ima_get_action(file_mnt_user_ns(vma->vm_file), inode,
- current_cred(), secid, MAY_EXEC, MMAP_CHECK,
- &pcr, &template, NULL, NULL);
+ current_cred(), blob.secid[0], MAY_EXEC,
+ MMAP_CHECK, &pcr, &template, NULL, NULL);
/* Is the mmap'ed file in policy? */
if (!(action & (IMA_MEASURE | IMA_APPRAISE_SUBMASK)))
@@ -486,10 +487,12 @@ int ima_bprm_check(struct linux_binprm *bprm)
{
int ret;
u32 secid;
+ struct lsmblob blob;
- security_current_getsecid_subj(&secid);
- ret = process_measurement(bprm->file, current_cred(), secid, NULL, 0,
- MAY_EXEC, BPRM_CHECK);
+ security_current_getsecid_subj(&blob);
+ /* scaffolding until process_measurement changes */
+ ret = process_measurement(bprm->file, current_cred(), blob.secid[0],
+ NULL, 0, MAY_EXEC, BPRM_CHECK);
if (ret)
return ret;
@@ -510,10 +513,11 @@ int ima_bprm_check(struct linux_binprm *bprm)
*/
int ima_file_check(struct file *file, int mask)
{
- u32 secid;
+ struct lsmblob blob;
- security_current_getsecid_subj(&secid);
- return process_measurement(file, current_cred(), secid, NULL, 0,
+ security_current_getsecid_subj(&blob);
+ /* scaffolding until process_measurement changes */
+ return process_measurement(file, current_cred(), blob.secid[0], NULL, 0,
mask & (MAY_READ | MAY_WRITE | MAY_EXEC |
MAY_APPEND), FILE_CHECK);
}
@@ -689,7 +693,7 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id,
bool contents)
{
enum ima_hooks func;
- u32 secid;
+ struct lsmblob blob;
/*
* Do devices using pre-allocated memory run the risk of the
@@ -709,8 +713,9 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id,
/* Read entire file for all partial reads. */
func = read_idmap[read_id] ?: FILE_CHECK;
- security_current_getsecid_subj(&secid);
- return process_measurement(file, current_cred(), secid, NULL,
+ security_current_getsecid_subj(&blob);
+ /* scaffolding - until process_measurement changes */
+ return process_measurement(file, current_cred(), blob.secid[0], NULL,
0, MAY_READ, func);
}
@@ -739,7 +744,7 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
enum kernel_read_file_id read_id)
{
enum ima_hooks func;
- u32 secid;
+ struct lsmblob blob;
/* permit signed certs */
if (!file && read_id == READING_X509_CERTIFICATE)
@@ -752,9 +757,10 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
}
func = read_idmap[read_id] ?: FILE_CHECK;
- security_current_getsecid_subj(&secid);
- return process_measurement(file, current_cred(), secid, buf, size,
- MAY_READ, func);
+ security_current_getsecid_subj(&blob);
+ /* scaffolding - until process_measurement changes */
+ return process_measurement(file, current_cred(), blob.secid[0], buf,
+ size, MAY_READ, func);
}
/**
@@ -882,7 +888,7 @@ int process_buffer_measurement(struct user_namespace *mnt_userns,
int digest_hash_len = hash_digest_size[ima_hash_algo];
int violation = 0;
int action = 0;
- u32 secid;
+ struct lsmblob blob;
if (digest && digest_len < digest_hash_len)
return -EINVAL;
@@ -905,9 +911,10 @@ int process_buffer_measurement(struct user_namespace *mnt_userns,
* buffer measurements.
*/
if (func) {
- security_current_getsecid_subj(&secid);
+ security_current_getsecid_subj(&blob);
+ /* scaffolding */
action = ima_get_action(mnt_userns, inode, current_cred(),
- secid, 0, func, &pcr, &template,
+ blob.secid[0], 0, func, &pcr, &template,
func_data, NULL);
if (!(action & IMA_MEASURE) && !digest)
return -ENOENT;
diff --git a/security/security.c b/security/security.c
index 815200684bcf..e33fa677181d 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1909,17 +1909,30 @@ int security_task_getsid(struct task_struct *p)
return call_int_hook(task_getsid, 0, p);
}
-void security_current_getsecid_subj(u32 *secid)
+void security_current_getsecid_subj(struct lsmblob *blob)
{
- *secid = 0;
- call_void_hook(current_getsecid_subj, secid);
+ struct security_hook_list *hp;
+
+ lsmblob_init(blob, 0);
+ hlist_for_each_entry(hp, &security_hook_heads.current_getsecid_subj,
+ list) {
+ if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
+ continue;
+ hp->hook.current_getsecid_subj(&blob->secid[hp->lsmid->slot]);
+ }
}
EXPORT_SYMBOL(security_current_getsecid_subj);
-void security_task_getsecid_obj(struct task_struct *p, u32 *secid)
+void security_task_getsecid_obj(struct task_struct *p, struct lsmblob *blob)
{
- *secid = 0;
- call_void_hook(task_getsecid_obj, p, secid);
+ struct security_hook_list *hp;
+
+ lsmblob_init(blob, 0);
+ hlist_for_each_entry(hp, &security_hook_heads.task_getsecid_obj, list) {
+ if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
+ continue;
+ hp->hook.task_getsecid_obj(p, &blob->secid[hp->lsmid->slot]);
+ }
}
EXPORT_SYMBOL(security_task_getsecid_obj);
--
2.31.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v33 12/29] LSM: Use lsmblob in security_inode_getsecid
[not found] <20220310234632.16194-1-casey@schaufler-ca.com>
2022-03-10 23:46 ` [PATCH v33 11/29] LSM: Use lsmblob in security_current_getsecid Casey Schaufler
@ 2022-03-10 23:46 ` Casey Schaufler
2022-03-10 23:46 ` [PATCH v33 13/29] LSM: Use lsmblob in security_cred_getsecid Casey Schaufler
2022-03-10 23:46 ` [PATCH v33 15/29] LSM: Ensure the correct LSM context releaser Casey Schaufler
3 siblings, 0 replies; 7+ messages in thread
From: Casey Schaufler @ 2022-03-10 23:46 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux
Cc: casey, linux-audit, keescook, john.johansen, penguin-kernel, paul,
stephen.smalley.work, linux-kernel, linux-integrity
Change the security_inode_getsecid() interface to fill in a
lsmblob structure instead of a u32 secid. This allows for its
callers to gather data from all registered LSMs. Data is provided
for IMA and audit.
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
---
include/linux/security.h | 7 ++++---
kernel/auditsc.c | 6 +++++-
security/integrity/ima/ima_policy.c | 7 ++++---
security/security.c | 11 +++++++++--
4 files changed, 22 insertions(+), 9 deletions(-)
diff --git a/include/linux/security.h b/include/linux/security.h
index 5f20c0c68f67..6fc573d2c253 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -456,7 +456,7 @@ int security_inode_getsecurity(struct user_namespace *mnt_userns,
void **buffer, bool alloc);
int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags);
int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size);
-void security_inode_getsecid(struct inode *inode, u32 *secid);
+void security_inode_getsecid(struct inode *inode, struct lsmblob *blob);
int security_inode_copy_up(struct dentry *src, struct cred **new);
int security_inode_copy_up_xattr(const char *name);
int security_kernfs_init_security(struct kernfs_node *kn_dir,
@@ -1002,9 +1002,10 @@ static inline int security_inode_listsecurity(struct inode *inode, char *buffer,
return 0;
}
-static inline void security_inode_getsecid(struct inode *inode, u32 *secid)
+static inline void security_inode_getsecid(struct inode *inode,
+ struct lsmblob *blob)
{
- *secid = 0;
+ lsmblob_init(blob, 0);
}
static inline int security_inode_copy_up(struct dentry *src, struct cred **new)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 2570bf5979e0..6cd15abb99c7 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2248,13 +2248,17 @@ static void audit_copy_inode(struct audit_names *name,
const struct dentry *dentry,
struct inode *inode, unsigned int flags)
{
+ struct lsmblob blob;
+
name->ino = inode->i_ino;
name->dev = inode->i_sb->s_dev;
name->mode = inode->i_mode;
name->uid = inode->i_uid;
name->gid = inode->i_gid;
name->rdev = inode->i_rdev;
- security_inode_getsecid(inode, &name->osid);
+ security_inode_getsecid(inode, &blob);
+ /* scaffolding until osid is updated */
+ name->osid = blob.secid[0];
if (flags & AUDIT_INODE_NOEVAL) {
name->fcap_ver = -1;
return;
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 22952efcc0b0..34ecdd7b01f5 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -625,7 +625,7 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
return false;
for (i = 0; i < MAX_LSM_RULES; i++) {
int rc = 0;
- u32 osid;
+ struct lsmblob lsmdata;
if (!rule->lsm[i].rule) {
if (!rule->lsm[i].args_p)
@@ -637,8 +637,9 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
case LSM_OBJ_USER:
case LSM_OBJ_ROLE:
case LSM_OBJ_TYPE:
- security_inode_getsecid(inode, &osid);
- rc = ima_filter_rule_match(osid, rule->lsm[i].type,
+ security_inode_getsecid(inode, &lsmdata);
+ rc = ima_filter_rule_match(lsmdata.secid[rule->which],
+ rule->lsm[i].type,
Audit_equal,
rule->lsm[i].rule,
rule->which);
diff --git a/security/security.c b/security/security.c
index e33fa677181d..0253c925a272 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1553,9 +1553,16 @@ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer
}
EXPORT_SYMBOL(security_inode_listsecurity);
-void security_inode_getsecid(struct inode *inode, u32 *secid)
+void security_inode_getsecid(struct inode *inode, struct lsmblob *blob)
{
- call_void_hook(inode_getsecid, inode, secid);
+ struct security_hook_list *hp;
+
+ lsmblob_init(blob, 0);
+ hlist_for_each_entry(hp, &security_hook_heads.inode_getsecid, list) {
+ if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
+ continue;
+ hp->hook.inode_getsecid(inode, &blob->secid[hp->lsmid->slot]);
+ }
}
int security_inode_copy_up(struct dentry *src, struct cred **new)
--
2.31.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v33 13/29] LSM: Use lsmblob in security_cred_getsecid
[not found] <20220310234632.16194-1-casey@schaufler-ca.com>
2022-03-10 23:46 ` [PATCH v33 11/29] LSM: Use lsmblob in security_current_getsecid Casey Schaufler
2022-03-10 23:46 ` [PATCH v33 12/29] LSM: Use lsmblob in security_inode_getsecid Casey Schaufler
@ 2022-03-10 23:46 ` Casey Schaufler
2022-03-11 7:52 ` kernel test robot
` (2 more replies)
2022-03-10 23:46 ` [PATCH v33 15/29] LSM: Ensure the correct LSM context releaser Casey Schaufler
3 siblings, 3 replies; 7+ messages in thread
From: Casey Schaufler @ 2022-03-10 23:46 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux
Cc: casey, linux-audit, keescook, john.johansen, penguin-kernel, paul,
stephen.smalley.work, linux-kernel, linux-integrity
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(-)
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
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v33 15/29] LSM: Ensure the correct LSM context releaser
[not found] <20220310234632.16194-1-casey@schaufler-ca.com>
` (2 preceding siblings ...)
2022-03-10 23:46 ` [PATCH v33 13/29] LSM: Use lsmblob in security_cred_getsecid Casey Schaufler
@ 2022-03-10 23:46 ` Casey Schaufler
3 siblings, 0 replies; 7+ messages in thread
From: Casey Schaufler @ 2022-03-10 23:46 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux
Cc: casey, linux-audit, keescook, john.johansen, penguin-kernel, paul,
stephen.smalley.work, linux-kernel, Chuck Lever, linux-integrity,
netdev, netfilter-devel, linux-nfs
Add a new lsmcontext data structure to hold all the information
about a "security context", including the string, its size and
which LSM allocated the string. The allocation information is
necessary because LSMs have different policies regarding the
lifecycle of these strings. SELinux allocates and destroys
them on each use, whereas Smack provides a pointer to an entry
in a list that never goes away.
Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: John Johansen <john.johansen@canonical.com>
Acked-by: Paul Moore <paul@paul-moore.com>
Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Acked-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Cc: linux-integrity@vger.kernel.org
Cc: netdev@vger.kernel.org
Cc: linux-audit@redhat.com
Cc: netfilter-devel@vger.kernel.org
To: Pablo Neira Ayuso <pablo@netfilter.org>
Cc: linux-nfs@vger.kernel.org
---
drivers/android/binder.c | 10 ++++---
fs/ceph/xattr.c | 6 ++++-
fs/nfs/nfs4proc.c | 8 ++++--
fs/nfsd/nfs4xdr.c | 7 +++--
include/linux/security.h | 35 +++++++++++++++++++++++--
include/net/scm.h | 5 +++-
kernel/audit.c | 14 +++++++---
kernel/auditsc.c | 12 ++++++---
net/ipv4/ip_sockglue.c | 4 ++-
net/netfilter/nf_conntrack_netlink.c | 4 ++-
net/netfilter/nf_conntrack_standalone.c | 4 ++-
net/netfilter/nfnetlink_queue.c | 13 ++++++---
net/netlabel/netlabel_unlabeled.c | 19 +++++++++++---
net/netlabel/netlabel_user.c | 4 ++-
security/security.c | 11 ++++----
15 files changed, 121 insertions(+), 35 deletions(-)
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 26838061defb..2125b4b795da 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2725,6 +2725,7 @@ static void binder_transaction(struct binder_proc *proc,
int t_debug_id = atomic_inc_return(&binder_last_id);
char *secctx = NULL;
u32 secctx_sz = 0;
+ struct lsmcontext scaff; /* scaffolding */
struct list_head sgc_head;
struct list_head pf_head;
const void __user *user_buffer = (const void __user *)
@@ -3033,7 +3034,8 @@ static void binder_transaction(struct binder_proc *proc,
t->security_ctx = 0;
WARN_ON(1);
}
- security_release_secctx(secctx, secctx_sz);
+ lsmcontext_init(&scaff, secctx, secctx_sz, 0);
+ security_release_secctx(&scaff);
secctx = NULL;
}
t->buffer->debug_id = t->debug_id;
@@ -3433,8 +3435,10 @@ static void binder_transaction(struct binder_proc *proc,
binder_alloc_free_buf(&target_proc->alloc, t->buffer);
err_binder_alloc_buf_failed:
err_bad_extra_size:
- if (secctx)
- security_release_secctx(secctx, secctx_sz);
+ if (secctx) {
+ lsmcontext_init(&scaff, secctx, secctx_sz, 0);
+ security_release_secctx(&scaff);
+ }
err_get_secctx_failed:
kfree(tcomplete);
binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index fcf7dfdecf96..df2b3bf46364 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -1374,12 +1374,16 @@ int ceph_security_init_secctx(struct dentry *dentry, umode_t mode,
void ceph_release_acl_sec_ctx(struct ceph_acl_sec_ctx *as_ctx)
{
+#ifdef CONFIG_CEPH_FS_SECURITY_LABEL
+ struct lsmcontext scaff; /* scaffolding */
+#endif
#ifdef CONFIG_CEPH_FS_POSIX_ACL
posix_acl_release(as_ctx->acl);
posix_acl_release(as_ctx->default_acl);
#endif
#ifdef CONFIG_CEPH_FS_SECURITY_LABEL
- security_release_secctx(as_ctx->sec_ctx, as_ctx->sec_ctxlen);
+ lsmcontext_init(&scaff, as_ctx->sec_ctx, as_ctx->sec_ctxlen, 0);
+ security_release_secctx(&scaff);
#endif
if (as_ctx->pagelist)
ceph_pagelist_release(as_ctx->pagelist);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index b18f31b2c9e7..c6237b5ddd93 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -133,8 +133,12 @@ nfs4_label_init_security(struct inode *dir, struct dentry *dentry,
static inline void
nfs4_label_release_security(struct nfs4_label *label)
{
- if (label)
- security_release_secctx(label->label, label->len);
+ struct lsmcontext scaff; /* scaffolding */
+
+ if (label) {
+ lsmcontext_init(&scaff, label->label, label->len, 0);
+ security_release_secctx(&scaff);
+ }
}
static inline u32 *nfs4_bitmask(struct nfs_server *server, struct nfs4_label *label)
{
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 899de438e529..fedc4b0292d6 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2830,6 +2830,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
int err;
struct nfs4_acl *acl = NULL;
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+ struct lsmcontext scaff; /* scaffolding */
void *context = NULL;
int contextlen;
#endif
@@ -3331,8 +3332,10 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
out:
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
- if (context)
- security_release_secctx(context, contextlen);
+ if (context) {
+ lsmcontext_init(&scaff, context, contextlen, 0); /*scaffolding*/
+ security_release_secctx(&scaff);
+ }
#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
kfree(acl);
if (tempfh) {
diff --git a/include/linux/security.h b/include/linux/security.h
index 9753bd9b4fdc..11c4d088f7a8 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -135,6 +135,37 @@ enum lockdown_reason {
extern const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1];
+/*
+ * A "security context" is the text representation of
+ * the information used by LSMs.
+ * This structure contains the string, its length, and which LSM
+ * it is useful for.
+ */
+struct lsmcontext {
+ char *context; /* Provided by the module */
+ u32 len;
+ int slot; /* Identifies the module */
+};
+
+/**
+ * lsmcontext_init - initialize an lsmcontext structure.
+ * @cp: Pointer to the context to initialize
+ * @context: Initial context, or NULL
+ * @size: Size of context, or 0
+ * @slot: Which LSM provided the context
+ *
+ * Fill in the lsmcontext from the provided information.
+ * This is a scaffolding function that will be removed when
+ * lsmcontext integration is complete.
+ */
+static inline void lsmcontext_init(struct lsmcontext *cp, char *context,
+ u32 size, int slot)
+{
+ cp->slot = slot;
+ cp->context = context;
+ cp->len = size;
+}
+
/*
* Data exported by the security modules
*
@@ -569,7 +600,7 @@ int security_ismaclabel(const char *name);
int security_secid_to_secctx(struct lsmblob *blob, char **secdata, u32 *seclen);
int security_secctx_to_secid(const char *secdata, u32 seclen,
struct lsmblob *blob);
-void security_release_secctx(char *secdata, u32 seclen);
+void security_release_secctx(struct lsmcontext *cp);
void security_inode_invalidate_secctx(struct inode *inode);
int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen);
int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
@@ -1432,7 +1463,7 @@ static inline int security_secctx_to_secid(const char *secdata,
return -EOPNOTSUPP;
}
-static inline void security_release_secctx(char *secdata, u32 seclen)
+static inline void security_release_secctx(struct lsmcontext *cp)
{
}
diff --git a/include/net/scm.h b/include/net/scm.h
index 23a35ff1b3f2..f273c4d777ec 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -92,6 +92,7 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
#ifdef CONFIG_SECURITY_NETWORK
static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
{
+ struct lsmcontext context;
struct lsmblob lb;
char *secdata;
u32 seclen;
@@ -106,7 +107,9 @@ static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct sc
if (!err) {
put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata);
- security_release_secctx(secdata, seclen);
+ /*scaffolding*/
+ lsmcontext_init(&context, secdata, seclen, 0);
+ security_release_secctx(&context);
}
}
}
diff --git a/kernel/audit.c b/kernel/audit.c
index c7cd039e258b..5aa2ee06c9e4 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1190,6 +1190,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
struct audit_sig_info *sig_data;
char *ctx = NULL;
u32 len;
+ struct lsmcontext scaff; /* scaffolding */
err = audit_netlink_ok(skb, msg_type);
if (err)
@@ -1447,15 +1448,18 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
}
sig_data = kmalloc(struct_size(sig_data, ctx, len), GFP_KERNEL);
if (!sig_data) {
- if (lsmblob_is_set(&audit_sig_lsm))
- security_release_secctx(ctx, len);
+ if (lsmblob_is_set(&audit_sig_lsm)) {
+ lsmcontext_init(&scaff, ctx, len, 0);
+ security_release_secctx(&scaff);
+ }
return -ENOMEM;
}
sig_data->uid = from_kuid(&init_user_ns, audit_sig_uid);
sig_data->pid = audit_sig_pid;
if (lsmblob_is_set(&audit_sig_lsm)) {
memcpy(sig_data->ctx, ctx, len);
- security_release_secctx(ctx, len);
+ lsmcontext_init(&scaff, ctx, len, 0);
+ security_release_secctx(&scaff);
}
audit_send_reply(skb, seq, AUDIT_SIGNAL_INFO, 0, 0,
sig_data, struct_size(sig_data, ctx, len));
@@ -2147,6 +2151,7 @@ int audit_log_task_context(struct audit_buffer *ab)
unsigned len;
int error;
struct lsmblob blob;
+ struct lsmcontext scaff; /* scaffolding */
security_current_getsecid_subj(&blob);
if (!lsmblob_is_set(&blob))
@@ -2161,7 +2166,8 @@ int audit_log_task_context(struct audit_buffer *ab)
}
audit_log_format(ab, " subj=%s", ctx);
- security_release_secctx(ctx, len);
+ lsmcontext_init(&scaff, ctx, len, 0);
+ security_release_secctx(&scaff);
return 0;
error_path:
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index c4c3666576c3..1626d8aabe83 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1121,6 +1121,7 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
struct lsmblob *blob, char *comm)
{
struct audit_buffer *ab;
+ struct lsmcontext lsmcxt;
char *ctx = NULL;
u32 len;
int rc = 0;
@@ -1138,7 +1139,8 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
rc = 1;
} else {
audit_log_format(ab, " obj=%s", ctx);
- security_release_secctx(ctx, len);
+ lsmcontext_init(&lsmcxt, ctx, len, 0); /*scaffolding*/
+ security_release_secctx(&lsmcxt);
}
}
audit_log_format(ab, " ocomm=");
@@ -1351,6 +1353,7 @@ static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
static void show_special(struct audit_context *context, int *call_panic)
{
+ struct lsmcontext lsmcxt;
struct audit_buffer *ab;
int i;
@@ -1385,7 +1388,8 @@ static void show_special(struct audit_context *context, int *call_panic)
*call_panic = 1;
} else {
audit_log_format(ab, " obj=%s", ctx);
- security_release_secctx(ctx, len);
+ lsmcontext_init(&lsmcxt, ctx, len, 0);
+ security_release_secctx(&lsmcxt);
}
}
if (context->ipc.has_perm) {
@@ -1542,6 +1546,7 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
char *ctx = NULL;
u32 len;
struct lsmblob blob;
+ struct lsmcontext lsmcxt;
lsmblob_init(&blob, n->osid);
if (security_secid_to_secctx(&blob, &ctx, &len)) {
@@ -1550,7 +1555,8 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
*call_panic = 2;
} else {
audit_log_format(ab, " obj=%s", ctx);
- security_release_secctx(ctx, len);
+ lsmcontext_init(&lsmcxt, ctx, len, 0); /* scaffolding */
+ security_release_secctx(&lsmcxt);
}
}
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 933a8f94f93a..70ca4510ea35 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -130,6 +130,7 @@ static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb,
static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
{
+ struct lsmcontext context;
struct lsmblob lb;
char *secdata;
u32 seclen, secid;
@@ -145,7 +146,8 @@ static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
return;
put_cmsg(msg, SOL_IP, SCM_SECURITY, seclen, secdata);
- security_release_secctx(secdata, seclen);
+ lsmcontext_init(&context, secdata, seclen, 0); /* scaffolding */
+ security_release_secctx(&context);
}
static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb)
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 073510c94b56..212e12b53adb 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -342,6 +342,7 @@ static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
int len, ret;
char *secctx;
struct lsmblob blob;
+ struct lsmcontext context;
/* lsmblob_init() puts ct->secmark into all of the secids in blob.
* security_secid_to_secctx() will know which security module
@@ -362,7 +363,8 @@ static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
ret = 0;
nla_put_failure:
- security_release_secctx(secctx, len);
+ lsmcontext_init(&context, secctx, len, 0); /* scaffolding */
+ security_release_secctx(&context);
return ret;
}
#else
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index bba3a66f5636..3b6ba86783f6 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -179,6 +179,7 @@ static void ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
u32 len;
char *secctx;
struct lsmblob blob;
+ struct lsmcontext context;
lsmblob_init(&blob, ct->secmark);
ret = security_secid_to_secctx(&blob, &secctx, &len);
@@ -187,7 +188,8 @@ static void ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
seq_printf(s, "secctx=%s ", secctx);
- security_release_secctx(secctx, len);
+ lsmcontext_init(&context, secctx, len, 0); /* scaffolding */
+ security_release_secctx(&context);
}
#else
static inline void ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index a9f7c9418ad3..d986bae1587b 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -397,6 +397,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
enum ip_conntrack_info ctinfo = 0;
const struct nfnl_ct_hook *nfnl_ct;
bool csum_verify;
+ struct lsmcontext scaff; /* scaffolding */
char *secdata = NULL;
u32 seclen = 0;
@@ -627,8 +628,10 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
}
nlh->nlmsg_len = skb->len;
- if (seclen)
- security_release_secctx(secdata, seclen);
+ if (seclen) {
+ lsmcontext_init(&scaff, secdata, seclen, 0);
+ security_release_secctx(&scaff);
+ }
return skb;
nla_put_failure:
@@ -636,8 +639,10 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
kfree_skb(skb);
net_err_ratelimited("nf_queue: error creating packet message\n");
nlmsg_failure:
- if (seclen)
- security_release_secctx(secdata, seclen);
+ if (seclen) {
+ lsmcontext_init(&scaff, secdata, seclen, 0);
+ security_release_secctx(&scaff);
+ }
return NULL;
}
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index c86df6ead742..a8e9ee202245 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -374,6 +374,7 @@ int netlbl_unlhsh_add(struct net *net,
struct net_device *dev;
struct netlbl_unlhsh_iface *iface;
struct audit_buffer *audit_buf = NULL;
+ struct lsmcontext context;
char *secctx = NULL;
u32 secctx_len;
struct lsmblob blob;
@@ -447,7 +448,9 @@ int netlbl_unlhsh_add(struct net *net,
&secctx,
&secctx_len) == 0) {
audit_log_format(audit_buf, " sec_obj=%s", secctx);
- security_release_secctx(secctx, secctx_len);
+ /* scaffolding */
+ lsmcontext_init(&context, secctx, secctx_len, 0);
+ security_release_secctx(&context);
}
audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
audit_log_end(audit_buf);
@@ -478,6 +481,7 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
struct netlbl_unlhsh_addr4 *entry;
struct audit_buffer *audit_buf;
struct net_device *dev;
+ struct lsmcontext context;
char *secctx;
u32 secctx_len;
struct lsmblob blob;
@@ -508,7 +512,9 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
security_secid_to_secctx(&blob,
&secctx, &secctx_len) == 0) {
audit_log_format(audit_buf, " sec_obj=%s", secctx);
- security_release_secctx(secctx, secctx_len);
+ /* scaffolding */
+ lsmcontext_init(&context, secctx, secctx_len, 0);
+ security_release_secctx(&context);
}
audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
audit_log_end(audit_buf);
@@ -545,6 +551,7 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
struct netlbl_unlhsh_addr6 *entry;
struct audit_buffer *audit_buf;
struct net_device *dev;
+ struct lsmcontext context;
char *secctx;
u32 secctx_len;
struct lsmblob blob;
@@ -574,7 +581,8 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
security_secid_to_secctx(&blob,
&secctx, &secctx_len) == 0) {
audit_log_format(audit_buf, " sec_obj=%s", secctx);
- security_release_secctx(secctx, secctx_len);
+ lsmcontext_init(&context, secctx, secctx_len, 0);
+ security_release_secctx(&context);
}
audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
audit_log_end(audit_buf);
@@ -1093,6 +1101,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
int ret_val = -ENOMEM;
struct netlbl_unlhsh_walk_arg *cb_arg = arg;
struct net_device *dev;
+ struct lsmcontext context;
void *data;
u32 secid;
char *secctx;
@@ -1163,7 +1172,9 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
NLBL_UNLABEL_A_SECCTX,
secctx_len,
secctx);
- security_release_secctx(secctx, secctx_len);
+ /* scaffolding */
+ lsmcontext_init(&context, secctx, secctx_len, 0);
+ security_release_secctx(&context);
if (ret_val != 0)
goto list_cb_failure;
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
index 893301ae0131..ef139d8ae7cd 100644
--- a/net/netlabel/netlabel_user.c
+++ b/net/netlabel/netlabel_user.c
@@ -84,6 +84,7 @@ struct audit_buffer *netlbl_audit_start_common(int type,
struct netlbl_audit *audit_info)
{
struct audit_buffer *audit_buf;
+ struct lsmcontext context;
char *secctx;
u32 secctx_len;
struct lsmblob blob;
@@ -103,7 +104,8 @@ struct audit_buffer *netlbl_audit_start_common(int type,
if (audit_info->secid != 0 &&
security_secid_to_secctx(&blob, &secctx, &secctx_len) == 0) {
audit_log_format(audit_buf, " subj=%s", secctx);
- security_release_secctx(secctx, secctx_len);
+ lsmcontext_init(&context, secctx, secctx_len, 0);/*scaffolding*/
+ security_release_secctx(&context);
}
return audit_buf;
diff --git a/security/security.c b/security/security.c
index 0bca482166d8..163cf0ae2429 100644
--- a/security/security.c
+++ b/security/security.c
@@ -2366,16 +2366,17 @@ int security_secctx_to_secid(const char *secdata, u32 seclen,
}
EXPORT_SYMBOL(security_secctx_to_secid);
-void security_release_secctx(char *secdata, u32 seclen)
+void security_release_secctx(struct lsmcontext *cp)
{
struct security_hook_list *hp;
- int ilsm = lsm_task_ilsm(current);
hlist_for_each_entry(hp, &security_hook_heads.release_secctx, list)
- if (ilsm == LSMBLOB_INVALID || ilsm == hp->lsmid->slot) {
- hp->hook.release_secctx(secdata, seclen);
- return;
+ if (cp->slot == hp->lsmid->slot) {
+ hp->hook.release_secctx(cp->context, cp->len);
+ break;
}
+
+ memset(cp, 0, sizeof(*cp));
}
EXPORT_SYMBOL(security_release_secctx);
--
2.31.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v33 13/29] LSM: Use lsmblob in security_cred_getsecid
2022-03-10 23:46 ` [PATCH v33 13/29] LSM: Use lsmblob in security_cred_getsecid Casey Schaufler
@ 2022-03-11 7:52 ` kernel test robot
2022-03-11 9:16 ` kernel test robot
2022-03-12 4:50 ` kernel test robot
2 siblings, 0 replies; 7+ messages in thread
From: kernel test robot @ 2022-03-11 7:52 UTC (permalink / raw)
To: Casey Schaufler, casey.schaufler, jmorris, linux-security-module,
selinux
Cc: kbuild-all, casey, linux-audit, keescook, john.johansen,
penguin-kernel, paul, stephen.smalley.work, linux-kernel,
linux-integrity
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
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v33 13/29] LSM: Use lsmblob in security_cred_getsecid
2022-03-10 23:46 ` [PATCH v33 13/29] LSM: Use lsmblob in security_cred_getsecid Casey Schaufler
2022-03-11 7:52 ` kernel test robot
@ 2022-03-11 9:16 ` kernel test robot
2022-03-12 4:50 ` kernel test robot
2 siblings, 0 replies; 7+ messages in thread
From: kernel test robot @ 2022-03-11 9:16 UTC (permalink / raw)
To: Casey Schaufler, casey.schaufler, jmorris, linux-security-module,
selinux
Cc: llvm, kbuild-all, casey, linux-audit, keescook, john.johansen,
penguin-kernel, paul, stephen.smalley.work, linux-kernel,
linux-integrity
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
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v33 13/29] LSM: Use lsmblob in security_cred_getsecid
2022-03-10 23:46 ` [PATCH v33 13/29] LSM: Use lsmblob in security_cred_getsecid Casey Schaufler
2022-03-11 7:52 ` kernel test robot
2022-03-11 9:16 ` kernel test robot
@ 2022-03-12 4:50 ` kernel test robot
2 siblings, 0 replies; 7+ messages in thread
From: kernel test robot @ 2022-03-12 4:50 UTC (permalink / raw)
To: Casey Schaufler, casey.schaufler, jmorris, linux-security-module,
selinux
Cc: kbuild-all, casey, linux-audit, keescook, john.johansen,
penguin-kernel, paul, stephen.smalley.work, linux-kernel,
linux-integrity
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
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2022-03-12 4:51 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20220310234632.16194-1-casey@schaufler-ca.com>
2022-03-10 23:46 ` [PATCH v33 11/29] LSM: Use lsmblob in security_current_getsecid Casey Schaufler
2022-03-10 23:46 ` [PATCH v33 12/29] LSM: Use lsmblob in security_inode_getsecid Casey Schaufler
2022-03-10 23:46 ` [PATCH v33 13/29] LSM: Use lsmblob in security_cred_getsecid Casey Schaufler
2022-03-11 7:52 ` kernel test robot
2022-03-11 9:16 ` kernel test robot
2022-03-12 4:50 ` kernel test robot
2022-03-10 23:46 ` [PATCH v33 15/29] LSM: Ensure the correct LSM context releaser Casey Schaufler
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox