--- v12
+++ v24
@@ -1,211 +1,90 @@
-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.
+Provide interfaces to map LSM slot numbers and LSM names.
+Update the LSM registration code to save this information.
-Change the users of security_audit_rule_match to use the
-lsmblob instead of a u32. In some cases this requires a
-temporary conversion using lsmblob_init() that will go
-away when other interfaces get converted.
-
-Reviewed-by: Kees Cook <keescook@chromium.org>
-Reviewed-by: John Johansen <john.johansen@canonical.com>
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
- include/linux/security.h | 7 ++++---
- kernel/auditfilter.c | 7 +++++--
- kernel/auditsc.c | 14 ++++++++++----
- security/integrity/ima/ima.h | 4 ++--
- security/integrity/ima/ima_policy.c | 7 +++++--
- security/security.c | 18 +++++++++++++++---
- 6 files changed, 41 insertions(+), 16 deletions(-)
+ include/linux/security.h | 4 ++++
+ security/security.c | 45 ++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 49 insertions(+)
diff --git a/include/linux/security.h b/include/linux/security.h
-index b74dc70088ca..9c6dbe248eaf 100644
+index 4a109092a8d7..a99a4307176f 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
-@@ -1837,7 +1837,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
-@@ -1853,8 +1854,8 @@ static inline int security_audit_rule_known(struct audit_krule *krule)
- return 0;
+@@ -192,6 +192,10 @@ static inline bool lsmblob_equal(struct lsmblob *bloba, struct lsmblob *blobb)
+ return !memcmp(bloba, blobb, sizeof(*bloba));
}
--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 b0126e9c0743..356db1dd276c 100644
---- a/kernel/auditfilter.c
-+++ b/kernel/auditfilter.c
-@@ -1325,6 +1325,7 @@ int audit_filter(int msgtype, unsigned int listtype)
- struct audit_field *f = &e->rule.fields[i];
- pid_t pid;
- u32 sid;
-+ struct lsmblob blob;
-
- switch (f->type) {
- case AUDIT_PID:
-@@ -1355,8 +1356,10 @@ int audit_filter(int msgtype, unsigned int listtype)
- case AUDIT_SUBJ_CLR:
- if (f->lsm_rule) {
- security_task_getsecid(current, &sid);
-- result = security_audit_rule_match(sid,
-- f->type, f->op, f->lsm_rule);
-+ lsmblob_init(&blob, sid);
-+ 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 4effe01ebbe2..7566e5b1c419 100644
---- a/kernel/auditsc.c
-+++ b/kernel/auditsc.c
-@@ -445,6 +445,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;
-
- cred = rcu_dereference_check(tsk->cred, tsk == current || task_creation);
-@@ -643,7 +644,9 @@ static int audit_filter_rules(struct task_struct *tsk,
- security_task_getsecid(tsk, &sid);
- need_sid = 0;
- }
-- result = security_audit_rule_match(sid, f->type,
-+ lsmblob_init(&blob, sid);
-+ result = security_audit_rule_match(&blob,
-+ f->type,
- f->op,
- f->lsm_rule);
- }
-@@ -658,15 +661,17 @@ static int audit_filter_rules(struct task_struct *tsk,
- if (f->lsm_rule) {
- /* Find files that match */
- if (name) {
-+ lsmblob_init(&blob, 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) {
-+ lsmblob_init(&blob, n->osid);
- if (security_audit_rule_match(
-- n->osid,
-+ &blob,
- f->type,
- f->op,
- f->lsm_rule)) {
-@@ -678,7 +683,8 @@ 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,
-+ lsmblob_init(&blob, ctx->ipc.osid);
-+ if (security_audit_rule_match(&blob,
- f->type, f->op,
- f->lsm_rule))
- ++result;
-diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
-index df4ca482fb53..d95b0ece7434 100644
---- a/security/integrity/ima/ima.h
-+++ b/security/integrity/ima/ima.h
-@@ -381,8 +381,8 @@ static inline int security_filter_rule_init(u32 field, u32 op, char *rulestr,
- return -EINVAL;
- }
-
--static inline int security_filter_rule_match(u32 secid, u32 field, u32 op,
-- void *lsmrule)
-+static inline int security_filter_rule_match(struct lsmblob *blob, u32 field,
-+ u32 op, void *lsmrule)
- {
- return -EINVAL;
- }
-diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
-index f19a895ad7cd..193ddd55420b 100644
---- a/security/integrity/ima/ima_policy.c
-+++ b/security/integrity/ima/ima_policy.c
-@@ -414,6 +414,7 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
- for (i = 0; i < MAX_LSM_RULES; i++) {
- int rc = 0;
- u32 osid;
-+ struct lsmblob blob;
-
- if (!rule->lsm[i].rule)
- continue;
-@@ -423,7 +424,8 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
- case LSM_OBJ_ROLE:
- case LSM_OBJ_TYPE:
- security_inode_getsecid(inode, &osid);
-- rc = security_filter_rule_match(osid,
-+ lsmblob_init(&blob, osid);
-+ rc = security_filter_rule_match(&blob,
- rule->lsm[i].type,
- Audit_equal,
- rule->lsm[i].rule);
-@@ -431,7 +433,8 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
- case LSM_SUBJ_USER:
- case LSM_SUBJ_ROLE:
- case LSM_SUBJ_TYPE:
-- rc = security_filter_rule_match(secid,
-+ lsmblob_init(&blob, secid);
-+ rc = security_filter_rule_match(&blob,
- rule->lsm[i].type,
- Audit_equal,
- rule->lsm[i].rule);
++/* Map lsm names to blob slot numbers */
++extern int lsm_name_to_slot(char *name);
++extern const char *lsm_slot_to_name(int slot);
++
+ /* These functions are in security/commoncap.c */
+ extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
+ int cap, unsigned int opts);
diff --git a/security/security.c b/security/security.c
-index a89634af639a..bfea9739c084 100644
+index 39dce9eb3bcd..05ce02ae7c46 100644
--- a/security/security.c
+++ b/security/security.c
-@@ -439,7 +439,7 @@ static int lsm_append(const char *new, char **result)
- /*
+@@ -474,6 +474,50 @@ static int lsm_append(const char *new, char **result)
* Current index to use while initializing the lsmblob secid list.
*/
--static int lsm_slot __initdata;
-+static int lsm_slot __lsm_ro_after_init;
+ static int lsm_slot __lsm_ro_after_init;
++static struct lsm_id *lsm_slotlist[LSMBLOB_ENTRIES] __lsm_ro_after_init;
++
++/**
++ * lsm_name_to_slot - Report the slot number for a security module
++ * @name: name of the security module
++ *
++ * Look up the slot number for the named security module.
++ * Returns the slot number or LSMBLOB_INVALID if @name is not
++ * a registered security module name.
++ */
++int lsm_name_to_slot(char *name)
++{
++ int i;
++
++ for (i = 0; i < lsm_slot; i++)
++ if (strcmp(lsm_slotlist[i]->lsm, name) == 0)
++ return i;
++
++ return LSMBLOB_INVALID;
++}
++
++/**
++ * lsm_slot_to_name - Get the name of the security module in a slot
++ * @slot: index into the interface LSM slot list.
++ *
++ * Provide the name of the security module associated with
++ * a interface LSM slot.
++ *
++ * If @slot is LSMBLOB_INVALID return the value
++ * for slot 0 if it has been set, otherwise NULL.
++ *
++ * Returns a pointer to the name string or NULL.
++ */
++const char *lsm_slot_to_name(int slot)
++{
++ if (slot == LSMBLOB_INVALID)
++ slot = 0;
++ else if (slot >= LSMBLOB_ENTRIES || slot < 0)
++ return NULL;
++
++ if (lsm_slotlist[slot] == NULL)
++ return NULL;
++ return lsm_slotlist[slot]->lsm;
++}
/**
* security_add_hooks - Add a modules hooks to the hook lists.
-@@ -2412,9 +2412,21 @@ void security_audit_rule_free(void *lsmrule)
- call_void_hook(audit_rule_free, lsmrule);
- }
-
--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);
-+ struct security_hook_list *hp;
-+ int rc;
-+
-+ hlist_for_each_entry(hp, &security_hook_heads.audit_rule_match, list) {
-+ if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
-+ continue;
-+ rc = hp->hook.audit_rule_match(blob->secid[hp->lsmid->slot],
-+ field, op, lsmrule);
-+ if (rc != 0)
-+ return rc;
-+ }
-+ return 0;
- }
- #endif /* CONFIG_AUDIT */
-
+@@ -493,6 +537,7 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count,
+ if (lsmid->slot == LSMBLOB_NEEDED) {
+ if (lsm_slot >= LSMBLOB_ENTRIES)
+ panic("%s Too many LSMs registered.\n", __func__);
++ lsm_slotlist[lsm_slot] = lsmid;
+ lsmid->slot = lsm_slot++;
+ init_debug("%s assigned lsmblob slot %d\n", lsmid->lsm,
+ lsmid->slot);
--
-2.20.1
+2.25.4