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 <casey@schaufler-ca.com>
Acked-by: Paul Moore <paul@paul-moore.com>
Reviewed-by: John Johansen <john.johansen@canonical.com>
---
include/linux/lsm_hook_defs.h | 3 ++-
include/linux/security.h | 7 ++++---
kernel/auditfilter.c | 11 +++++++----
kernel/auditsc.c | 18 ++++++++++++++----
security/apparmor/audit.c | 8 ++++++--
security/apparmor/include/audit.h | 2 +-
security/integrity/ima/ima_policy.c | 11 +++++++----
security/security.c | 7 ++++---
security/selinux/include/audit.h | 5 +++--
security/selinux/ss/services.c | 11 ++++++++---
security/smack/smack_lsm.c | 11 ++++++++---
11 files changed, 64 insertions(+), 30 deletions(-)
diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
index 855db460e08b..1d3bdf71109e 100644
--- a/include/linux/lsm_hook_defs.h
+++ b/include/linux/lsm_hook_defs.h
@@ -416,7 +416,8 @@ LSM_HOOK(void, LSM_RET_VOID, key_post_create_or_update, struct key *keyring,
LSM_HOOK(int, 0, audit_rule_init, u32 field, u32 op, char *rulestr,
void **lsmrule, gfp_t gfp)
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)
+LSM_HOOK(int, 0, audit_rule_match, struct lsmblob *blob, u32 field, u32 op,
+ void *lsmrule)
LSM_HOOK(void, LSM_RET_VOID, audit_rule_free, void *lsmrule)
#endif /* CONFIG_AUDIT */
diff --git a/include/linux/security.h b/include/linux/security.h
index 0057a22137e8..c0ed2119a622 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -2071,7 +2071,8 @@ static inline void security_key_post_create_or_update(struct key *keyring,
int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule,
gfp_t gfp);
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
@@ -2087,8 +2088,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;
}
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index d6ef4f4f9cba..c4c7cda3b846 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -1339,8 +1339,8 @@ 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;
switch (f->type) {
case AUDIT_PID:
@@ -1370,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);
+ /* 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..23adb15cae43 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,
+ /* 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) {
+ /* 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) {
+ /* 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,
+ /* 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 6b5181c668b5..758b75a9c1c5 100644
--- a/security/apparmor/audit.c
+++ b/security/apparmor/audit.c
@@ -264,13 +264,17 @@ 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 aa_audit_rule_match(struct lsmblob *blob, u32 field, u32 op, void *vrule)
{
struct aa_audit_rule *rule = vrule;
struct aa_label *label;
int found = 0;
- label = aa_secid_to_label(sid);
+ /* 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 0c8cc86b417b..c5a516e61318 100644
--- a/security/apparmor/include/audit.h
+++ b/security/apparmor/include/audit.h
@@ -202,6 +202,6 @@ static inline int complain_error(int error)
void aa_audit_rule_free(void *vrule);
int aa_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule, gfp_t gfp);
int aa_audit_rule_known(struct audit_krule *rule);
-int aa_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule);
+int aa_audit_rule_match(struct lsmblob *blob, u32 field, u32 op, void *vrule);
#endif /* __AA_AUDIT_H */
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 09da8e639239..40119816b848 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -635,7 +635,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)
@@ -649,15 +649,18 @@ 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, lsm_rule->lsm[i].type,
+ /* 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);
break;
case LSM_SUBJ_USER:
case LSM_SUBJ_ROLE:
case LSM_SUBJ_TYPE:
- rc = ima_filter_rule_match(secid, lsm_rule->lsm[i].type,
+ /* scaffolding */
+ blob.scaffold.secid = secid;
+ rc = ima_filter_rule_match(&blob, lsm_rule->lsm[i].type,
Audit_equal,
lsm_rule->lsm[i].rule);
break;
diff --git a/security/security.c b/security/security.c
index 8cee5b6c6e6d..64a6d6bbd1f4 100644
--- a/security/security.c
+++ b/security/security.c
@@ -5399,7 +5399,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
@@ -5410,9 +5410,10 @@ 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, secid, field, op, lsmrule);
+ return call_int_hook(audit_rule_match, blob, field, op, lsmrule);
}
#endif /* CONFIG_AUDIT */
diff --git a/security/selinux/include/audit.h b/security/selinux/include/audit.h
index 29c7d4c86f6d..104165e4c931 100644
--- a/security/selinux/include/audit.h
+++ b/security/selinux/include/audit.h
@@ -41,7 +41,7 @@ void selinux_audit_rule_free(void *rule);
/**
* 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
@@ -49,7 +49,8 @@ void selinux_audit_rule_free(void *rule);
* 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 selinux_audit_rule_match(struct lsmblob *blob, u32 field, u32 op,
+ void *rule);
/**
* 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 e33e55384b75..43eb1d46942c 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -3633,7 +3633,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 selinux_audit_rule_match(struct lsmblob *blob, u32 field, u32 op,
+ void *vrule)
{
struct selinux_state *state = &selinux_state;
struct selinux_policy *policy;
@@ -3659,10 +3660,14 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule)
goto out;
}
- ctxt = sidtab_search(policy->sidtab, sid);
+ /* 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 4164699cd4f6..52d5ef986db8 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -4776,7 +4776,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
@@ -4784,7 +4784,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)
+static int smack_audit_rule_match(struct lsmblob *blob, u32 field, u32 op,
+ void *vrule)
{
struct smack_known *skp;
char *rule = vrule;
@@ -4797,7 +4798,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);
+ /* 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,
--
2.41.0
Hi Casey,
kernel test robot noticed the following build warnings:
[auto build test WARNING on pcmoore-selinux/next]
[also build test WARNING on zohar-integrity/next-integrity linus/master pcmoore-audit/next v6.11-rc5 next-20240826]
[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#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Casey-Schaufler/LSM-Add-the-lsmblob-data-structure/20240826-170520
base: https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git next
patch link: https://lore.kernel.org/r/20240825190048.13289-3-casey%40schaufler-ca.com
patch subject: [PATCH 02/13] LSM: Use lsmblob in security_audit_rule_match
config: i386-buildonly-randconfig-006-20240827 (https://download.01.org/0day-ci/archive/20240827/202408270317.8wTE4P5l-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240827/202408270317.8wTE4P5l-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202408270317.8wTE4P5l-lkp@intel.com/
All warnings (new ones prefixed by >>):
security/integrity/ima/ima_policy.c: In function 'ima_match_rules':
>> security/integrity/ima/ima_policy.c:654:52: warning: passing argument 1 of 'ima_filter_rule_match' makes integer from pointer without a cast [-Wint-conversion]
654 | rc = ima_filter_rule_match(&blob, lsm_rule->lsm[i].type,
| ^~~~~
| |
| struct lsmblob *
In file included from security/integrity/ima/ima_policy.c:22:
security/integrity/ima/ima.h:558:45: note: expected 'u32' {aka 'unsigned int'} but argument is of type 'struct lsmblob *'
558 | static inline int ima_filter_rule_match(u32 secid, u32 field, u32 op,
| ~~~~^~~~~
security/integrity/ima/ima_policy.c:663:52: warning: passing argument 1 of 'ima_filter_rule_match' makes integer from pointer without a cast [-Wint-conversion]
663 | rc = ima_filter_rule_match(&blob, lsm_rule->lsm[i].type,
| ^~~~~
| |
| struct lsmblob *
security/integrity/ima/ima.h:558:45: note: expected 'u32' {aka 'unsigned int'} but argument is of type 'struct lsmblob *'
558 | static inline int ima_filter_rule_match(u32 secid, u32 field, u32 op,
| ~~~~^~~~~
vim +/ima_filter_rule_match +654 security/integrity/ima/ima_policy.c
553
554 /**
555 * ima_match_rules - determine whether an inode matches the policy rule.
556 * @rule: a pointer to a rule
557 * @idmap: idmap of the mount the inode was found from
558 * @inode: a pointer to an inode
559 * @cred: a pointer to a credentials structure for user validation
560 * @secid: the secid of the task to be validated
561 * @func: LIM hook identifier
562 * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
563 * @func_data: func specific data, may be NULL
564 *
565 * Returns true on rule match, false on failure.
566 */
567 static bool ima_match_rules(struct ima_rule_entry *rule,
568 struct mnt_idmap *idmap,
569 struct inode *inode, const struct cred *cred,
570 u32 secid, enum ima_hooks func, int mask,
571 const char *func_data)
572 {
573 int i;
574 bool result = false;
575 struct ima_rule_entry *lsm_rule = rule;
576 bool rule_reinitialized = false;
577
578 if ((rule->flags & IMA_FUNC) &&
579 (rule->func != func && func != POST_SETATTR))
580 return false;
581
582 switch (func) {
583 case KEY_CHECK:
584 case CRITICAL_DATA:
585 return ((rule->func == func) &&
586 ima_match_rule_data(rule, func_data, cred));
587 default:
588 break;
589 }
590
591 if ((rule->flags & IMA_MASK) &&
592 (rule->mask != mask && func != POST_SETATTR))
593 return false;
594 if ((rule->flags & IMA_INMASK) &&
595 (!(rule->mask & mask) && func != POST_SETATTR))
596 return false;
597 if ((rule->flags & IMA_FSMAGIC)
598 && rule->fsmagic != inode->i_sb->s_magic)
599 return false;
600 if ((rule->flags & IMA_FSNAME)
601 && strcmp(rule->fsname, inode->i_sb->s_type->name))
602 return false;
603 if ((rule->flags & IMA_FSUUID) &&
604 !uuid_equal(&rule->fsuuid, &inode->i_sb->s_uuid))
605 return false;
606 if ((rule->flags & IMA_UID) && !rule->uid_op(cred->uid, rule->uid))
607 return false;
608 if (rule->flags & IMA_EUID) {
609 if (has_capability_noaudit(current, CAP_SETUID)) {
610 if (!rule->uid_op(cred->euid, rule->uid)
611 && !rule->uid_op(cred->suid, rule->uid)
612 && !rule->uid_op(cred->uid, rule->uid))
613 return false;
614 } else if (!rule->uid_op(cred->euid, rule->uid))
615 return false;
616 }
617 if ((rule->flags & IMA_GID) && !rule->gid_op(cred->gid, rule->gid))
618 return false;
619 if (rule->flags & IMA_EGID) {
620 if (has_capability_noaudit(current, CAP_SETGID)) {
621 if (!rule->gid_op(cred->egid, rule->gid)
622 && !rule->gid_op(cred->sgid, rule->gid)
623 && !rule->gid_op(cred->gid, rule->gid))
624 return false;
625 } else if (!rule->gid_op(cred->egid, rule->gid))
626 return false;
627 }
628 if ((rule->flags & IMA_FOWNER) &&
629 !rule->fowner_op(i_uid_into_vfsuid(idmap, inode),
630 rule->fowner))
631 return false;
632 if ((rule->flags & IMA_FGROUP) &&
633 !rule->fgroup_op(i_gid_into_vfsgid(idmap, inode),
634 rule->fgroup))
635 return false;
636 for (i = 0; i < MAX_LSM_RULES; i++) {
637 int rc = 0;
638 struct lsmblob blob = { };
639
640 if (!lsm_rule->lsm[i].rule) {
641 if (!lsm_rule->lsm[i].args_p)
642 continue;
643 else
644 return false;
645 }
646
647 retry:
648 switch (i) {
649 case LSM_OBJ_USER:
650 case LSM_OBJ_ROLE:
651 case LSM_OBJ_TYPE:
652 /* scaffolding */
653 security_inode_getsecid(inode, &blob.scaffold.secid);
> 654 rc = ima_filter_rule_match(&blob, lsm_rule->lsm[i].type,
655 Audit_equal,
656 lsm_rule->lsm[i].rule);
657 break;
658 case LSM_SUBJ_USER:
659 case LSM_SUBJ_ROLE:
660 case LSM_SUBJ_TYPE:
661 /* scaffolding */
662 blob.scaffold.secid = secid;
663 rc = ima_filter_rule_match(&blob, lsm_rule->lsm[i].type,
664 Audit_equal,
665 lsm_rule->lsm[i].rule);
666 break;
667 default:
668 break;
669 }
670
671 if (rc == -ESTALE && !rule_reinitialized) {
672 lsm_rule = ima_lsm_copy_rule(rule, GFP_ATOMIC);
673 if (lsm_rule) {
674 rule_reinitialized = true;
675 goto retry;
676 }
677 }
678 if (!rc) {
679 result = false;
680 goto out;
681 }
682 }
683 result = true;
684
685 out:
686 if (rule_reinitialized) {
687 for (i = 0; i < MAX_LSM_RULES; i++)
688 ima_filter_rule_free(lsm_rule->lsm[i].rule);
689 kfree(lsm_rule);
690 }
691 return result;
692 }
693
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
© 2016 - 2025 Red Hat, Inc.