From 7b67a3349c08ac8807e04911c5400eec4c0af400 Mon Sep 17 00:00:00 2001 From: Casey Schaufler Date: Mon, 28 Aug 2023 16:59:26 -0700 Subject: [PATCH] UBUNTU: SAUCE: apparmor4.0.0 [05/90]: LSM stacking v39: LSM: Use lsmblob in security_audit_rule_match BugLink: http://bugs.launchpad.net/bugs/2028253 Change the secid parameter of security_audit_rule_match to a lsmblob structure pointer. Pass the entry from the lsmblob structure for the approprite slot to the LSM hook. Change the users of security_audit_rule_match to use the lsmblob instead of a u32. The scaffolding function lsmblob_init() fills the blob with the value of the old secid, ensuring that it is available to the appropriate module hook. The sources of the secid, security_task_getsecid() and security_inode_getsecid(), will be converted to use the blob structure later in the series. At the point the use of lsmblob_init() is dropped. Signed-off-by: Casey Schaufler Acked-by: Paul Moore Reviewed-by: John Johansen Cc: linux-audit@redhat.com (cherry picked from commit ec1eb9be88908dcb7e040a27c40f247b20ca5f21 https://git.launchpad.net/~apparmor-dev/ubuntu-kernel-next) Signed-off-by: Paolo Pisati --- include/linux/lsm_hook_defs.h | 4 ++-- include/linux/security.h | 13 +++++++------ kernel/auditfilter.c | 10 +++++++--- kernel/auditsc.c | 18 ++++++++++++++---- security/apparmor/audit.c | 10 ++++++++-- security/apparmor/include/audit.h | 3 ++- security/integrity/ima/ima_policy.c | 11 +++++++---- security/security.c | 12 ++++++------ security/selinux/include/audit.h | 5 +++-- security/selinux/ss/services.c | 11 ++++++++--- security/smack/smack_lsm.c | 12 ++++++++---- 11 files changed, 72 insertions(+), 37 deletions(-) diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index cf5a5fddfe2a..caac29ab1f5a 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -396,8 +396,8 @@ LSM_HOOK(int, 0, key_getsecurity, struct key *key, char **buffer) LSM_HOOK(int, 0, audit_rule_init, u32 field, u32 op, char *rulestr, void **lsmrule, int lsmid) LSM_HOOK(int, 0, audit_rule_known, struct audit_krule *krule) -LSM_HOOK(int, 0, audit_rule_match, u32 secid, u32 field, u32 op, void *lsmrule, - int lsmid) +LSM_HOOK(int, 0, audit_rule_match, struct lsmblob *blob, u32 field, u32 op, + void *lsmrule, int lsmid) LSM_HOOK(void, LSM_RET_VOID, audit_rule_free, void *lsmrule, int lsmid) #endif /* CONFIG_AUDIT */ diff --git a/include/linux/security.h b/include/linux/security.h index 239f10372b8a..ced4c2945082 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -2027,7 +2027,8 @@ static inline int security_key_getsecurity(struct key *key, char **_buffer) #ifdef CONFIG_SECURITY int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule); int security_audit_rule_known(struct audit_krule *krule); -int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule); +int security_audit_rule_match(struct lsmblob *blob, u32 field, u32 op, + void *lsmrule); void security_audit_rule_free(void *lsmrule); #else @@ -2043,8 +2044,8 @@ static inline int security_audit_rule_known(struct audit_krule *krule) return 0; } -static inline int security_audit_rule_match(u32 secid, u32 field, u32 op, - void *lsmrule) +static inline int security_audit_rule_match(struct lsmblob *blob, u32 field, + u32 op, void *lsmrule) { return 0; } @@ -2058,8 +2059,8 @@ static inline void security_audit_rule_free(void *lsmrule) #if defined(CONFIG_IMA_LSM_RULES) && defined(CONFIG_SECURITY) int ima_filter_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule, int lsmid); -int ima_filter_rule_match(u32 secid, u32 field, u32 op, void *lsmrule, - int lsmid); +int ima_filter_rule_match(struct lsmblob *blob, u32 field, u32 op, + void *lsmrule, int lsmid); void ima_filter_rule_free(void *lsmrule, int lsmid); #else @@ -2070,7 +2071,7 @@ static inline int ima_filter_rule_init(u32 field, u32 op, char *rulestr, return 0; } -static inline int ima_filter_rule_match(u32 secid, u32 field, u32 op, +static inline int ima_filter_rule_match(struct lsmblob *blob, u32 field, u32 op, void *lsmrule, int lsmid) { return 0; diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 8317a37dea0b..0a6a1c4c3507 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -1338,6 +1338,7 @@ int audit_filter(int msgtype, unsigned int listtype) for (i = 0; i < e->rule.field_count; i++) { struct audit_field *f = &e->rule.fields[i]; + struct lsmblob blob = { }; pid_t pid; u32 sid; @@ -1369,9 +1370,12 @@ int audit_filter(int msgtype, unsigned int listtype) case AUDIT_SUBJ_SEN: case AUDIT_SUBJ_CLR: if (f->lsm_rule) { - security_current_getsecid_subj(&sid); - result = security_audit_rule_match(sid, - f->type, f->op, f->lsm_rule); + /* stacking scaffolding */ + security_current_getsecid_subj( + &blob.scaffold.secid); + result = security_audit_rule_match( + &blob, f->type, f->op, + f->lsm_rule); } break; case AUDIT_EXE: diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 6f0d6fb6523f..fb001300f0c2 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -471,6 +471,7 @@ 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; if (ctx && rule->prio <= ctx->prio) @@ -681,7 +682,10 @@ static int audit_filter_rules(struct task_struct *tsk, security_current_getsecid_subj(&sid); need_sid = 0; } - result = security_audit_rule_match(sid, f->type, + /* stacking scaffolding */ + blob.scaffold.secid = sid; + result = security_audit_rule_match(&blob, + f->type, f->op, f->lsm_rule); } @@ -696,15 +700,19 @@ static int audit_filter_rules(struct task_struct *tsk, if (f->lsm_rule) { /* Find files that match */ if (name) { + /* stacking scaffolding */ + blob.scaffold.secid = name->osid; result = security_audit_rule_match( - name->osid, + &blob, f->type, f->op, f->lsm_rule); } else if (ctx) { list_for_each_entry(n, &ctx->names_list, list) { + /* stacking scaffolding */ + blob.scaffold.secid = n->osid; if (security_audit_rule_match( - n->osid, + &blob, f->type, f->op, f->lsm_rule)) { @@ -716,7 +724,9 @@ static int audit_filter_rules(struct task_struct *tsk, /* Find ipc objects that match */ if (!ctx || ctx->type != AUDIT_IPC) break; - if (security_audit_rule_match(ctx->ipc.osid, + /* stacking scaffolding */ + blob.scaffold.secid = ctx->ipc.osid; + if (security_audit_rule_match(&blob, f->type, f->op, f->lsm_rule)) ++result; diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c index 0c9c94129004..37aa333adbea 100644 --- a/security/apparmor/audit.c +++ b/security/apparmor/audit.c @@ -270,7 +270,8 @@ int aa_audit_rule_known(struct audit_krule *rule) return 0; } -int aa_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, int lsmid) +int aa_audit_rule_match(struct lsmblob *blob, u32 field, u32 op, void *vrule, + int lsmid) { struct aa_audit_rule *rule = vrule; struct aa_label *label; @@ -278,7 +279,12 @@ int aa_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, int lsmid) if (lsmid != LSM_ID_UNDEF || lsmid != LSM_ID_APPARMOR) return 0; - label = aa_secid_to_label(sid); + + /* stacking scaffolding */ + if (!blob->apparmor.label && blob->scaffold.secid) + label = aa_secid_to_label(blob->scaffold.secid); + else + label = blob->apparmor.label; if (!label) return -ENOENT; diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h index a75c45dd059f..ae3fc4089b00 100644 --- a/security/apparmor/include/audit.h +++ b/security/apparmor/include/audit.h @@ -203,6 +203,7 @@ void aa_audit_rule_free(void *vrule, int lsmid); int aa_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule, int lsmid); int aa_audit_rule_known(struct audit_krule *rule); -int aa_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, int lsmid); +int aa_audit_rule_match(struct lsmblob *blob, u32 field, u32 op, void *vrule, + int lsmid); #endif /* __AA_AUDIT_H */ diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index a563e0478cc6..d24205aa1beb 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -657,7 +657,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 blob = { }; if (!lsm_rule->lsm[i].rule) { if (!lsm_rule->lsm[i].args_p) @@ -671,8 +671,9 @@ retry: case LSM_OBJ_USER: case LSM_OBJ_ROLE: case LSM_OBJ_TYPE: - security_inode_getsecid(inode, &osid); - rc = ima_filter_rule_match(osid, lsm_rule->lsm[i].type, + /* stacking scaffolding */ + security_inode_getsecid(inode, &blob.scaffold.secid); + rc = ima_filter_rule_match(&blob, lsm_rule->lsm[i].type, Audit_equal, lsm_rule->lsm[i].rule, lsm_rule->lsm[i].lsm_id); @@ -680,7 +681,9 @@ retry: case LSM_SUBJ_USER: case LSM_SUBJ_ROLE: case LSM_SUBJ_TYPE: - rc = ima_filter_rule_match(secid, lsm_rule->lsm[i].type, + /* stacking scaffolding */ + blob.scaffold.secid = secid; + rc = ima_filter_rule_match(&blob, lsm_rule->lsm[i].type, Audit_equal, lsm_rule->lsm[i].rule, lsm_rule->lsm[i].lsm_id); diff --git a/security/security.c b/security/security.c index 615a6412edac..a02633d0ab7f 100644 --- a/security/security.c +++ b/security/security.c @@ -5462,7 +5462,7 @@ void security_audit_rule_free(void *lsmrule) /** * security_audit_rule_match() - Check if a label matches an audit rule - * @secid: security label + * @lsmblob: security label * @field: LSM audit field * @op: matching operator * @lsmrule: audit rule @@ -5473,9 +5473,9 @@ void security_audit_rule_free(void *lsmrule) * Return: Returns 1 if secid matches the rule, 0 if it does not, -ERRNO on * failure. */ -int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule) +int security_audit_rule_match(struct lsmblob *blob, u32 field, u32 op, void *lsmrule) { - return call_int_hook(audit_rule_match, 0, secid, field, op, lsmrule, + return call_int_hook(audit_rule_match, 0, blob, field, op, lsmrule, LSM_ID_UNDEF); } #endif /* CONFIG_AUDIT */ @@ -5497,10 +5497,10 @@ void ima_filter_rule_free(void *lsmrule, int lsmid) call_void_hook(audit_rule_free, lsmrule, lsmid); } -int ima_filter_rule_match(u32 secid, u32 field, u32 op, void *lsmrule, - int lsmid) +int ima_filter_rule_match(struct lsmblob *blob, u32 field, u32 op, + void *lsmrule, int lsmid) { - return call_int_hook(audit_rule_match, 0, secid, field, op, lsmrule, + return call_int_hook(audit_rule_match, 0, blob, field, op, lsmrule, lsmid); } #endif /* CONFIG_IMA_LSM_RULES */ diff --git a/security/selinux/include/audit.h b/security/selinux/include/audit.h index 9629eb1edb64..ecd6be8619a5 100644 --- a/security/selinux/include/audit.h +++ b/security/selinux/include/audit.h @@ -42,7 +42,7 @@ void selinux_audit_rule_free(void *rule, int lsmid); /** * selinux_audit_rule_match - determine if a context ID matches a rule. - * @sid: the context ID to check + * @blob: includes the context ID to check * @field: the field this rule refers to * @op: the operator the rule uses * @rule: pointer to the audit rule to check against @@ -51,7 +51,8 @@ void selinux_audit_rule_free(void *rule, int lsmid); * Returns 1 if the context id matches the rule, 0 if it does not, and * -errno on failure. */ -int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *rule, int lsmid); +int selinux_audit_rule_match(struct lsmblob *blob, u32 field, u32 op, + void *rule, int lsmid); /** * selinux_audit_rule_known - check to see if rule contains selinux fields. diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index ed71c7a077bf..c1dfe4baf58e 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -3638,7 +3638,8 @@ int selinux_audit_rule_known(struct audit_krule *rule) return 0; } -int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, int lsmid) +int selinux_audit_rule_match(struct lsmblob *blob, u32 field, u32 op, + void *vrule, int lsmid) { struct selinux_state *state = &selinux_state; struct selinux_policy *policy; @@ -3666,10 +3667,14 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, int lsmid) goto out; } - ctxt = sidtab_search(policy->sidtab, sid); + /* stacking scaffolding */ + if (!blob->selinux.secid && blob->scaffold.secid) + blob->selinux.secid = blob->scaffold.secid; + + ctxt = sidtab_search(policy->sidtab, blob->selinux.secid); if (unlikely(!ctxt)) { WARN_ONCE(1, "selinux_audit_rule_match: unrecognized SID %d\n", - sid); + blob->selinux.secid); match = -ENOENT; goto out; } diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 034312cd5037..644c925e43d1 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -4727,7 +4727,7 @@ static int smack_audit_rule_known(struct audit_krule *krule) /** * smack_audit_rule_match - Audit given object ? - * @secid: security id for identifying the object to test + * @blob: security id for identifying the object to test * @field: audit rule flags given from user-space * @op: required testing operator * @vrule: smack internal rule presentation @@ -4736,8 +4736,8 @@ static int smack_audit_rule_known(struct audit_krule *krule) * The core Audit hook. It's used to take the decision of * whether to audit or not to audit a given object. */ -static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule, - int lsmid) +static int smack_audit_rule_match(struct lsmblob *blob, u32 field, u32 op, + void *vrule, int lsmid) { struct smack_known *skp; char *rule = vrule; @@ -4752,7 +4752,11 @@ static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule, if (field != AUDIT_SUBJ_USER && field != AUDIT_OBJ_USER) return 0; - skp = smack_from_secid(secid); + /* stacking scaffolding */ + if (!blob->smack.skp && blob->scaffold.secid) + skp = smack_from_secid(blob->scaffold.secid); + else + skp = blob->smack.skp; /* * No need to do string comparisons. If a match occurs,