Inter-revision diff: patch 5

Comparing v31 (message) to v26 (message)

--- v31
+++ v26
@@ -1,284 +1,214 @@
-Integrity measurement may filter on security module information
-and needs to be clear in the case of multiple active security
-modules which applies. Provide a boot option ima_rules_lsm= to
-allow the user to specify an active security module to apply
-filters to. If not specified, use the first registered module
-that supports the audit_rule_match() LSM hook. Allow the user
-to specify in the IMA policy an lsm= option to specify the
-security module to use for a particular rule.
-
+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.
+
+Reviewed-by: Kees Cook <keescook@chromium.org>
+Reviewed-by: John Johansen <john.johansen@canonical.com>
+Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
+Acked-by: Paul Moore <paul@paul-moore.com>
 Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
+Cc: linux-audit@redhat.com
+Cc: linux-integrity@vger.kernel.org
 To: Mimi Zohar <zohar@linux.ibm.com>
-To: linux-integrity@vger.kernel.org
 ---
- Documentation/ABI/testing/ima_policy |  8 ++++-
- include/linux/security.h             | 14 ++++----
- security/integrity/ima/ima_policy.c  | 51 ++++++++++++++++++++++++----
- security/security.c                  | 35 +++++++++++++++----
- 4 files changed, 89 insertions(+), 19 deletions(-)
-
-diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
-index 839fab811b18..64863e9d87ea 100644
---- a/Documentation/ABI/testing/ima_policy
-+++ b/Documentation/ABI/testing/ima_policy
-@@ -26,7 +26,7 @@ Description:
- 				[uid=] [euid=] [gid=] [egid=]
- 				[fowner=] [fgroup=]]
- 			lsm:	[[subj_user=] [subj_role=] [subj_type=]
--				 [obj_user=] [obj_role=] [obj_type=]]
-+				 [obj_user=] [obj_role=] [obj_type=]] [lsm=]
- 			option:	[[appraise_type=]] [template=] [permit_directio]
- 				[appraise_flag=] [appraise_algos=] [keyrings=]
- 		  base:
-@@ -126,6 +126,12 @@ Description:
- 
- 			measure subj_user=_ func=FILE_CHECK mask=MAY_READ
- 
-+		It is possible to explicitly specify which security
-+		module a rule applies to using lsm=.  If the security
-+		module specified is not active on the system the rule
-+		will be rejected.  If lsm= is not specified the first
-+		security module registered on the system will be assumed.
-+
- 		Example of measure rules using alternate PCRs::
- 
- 			measure func=KEXEC_KERNEL_CHECK pcr=4
+ include/linux/security.h            |  7 ++++---
+ kernel/auditfilter.c                |  6 ++++--
+ kernel/auditsc.c                    | 16 +++++++++++-----
+ security/integrity/ima/ima.h        |  4 ++--
+ security/integrity/ima/ima_policy.c |  7 +++++--
+ security/security.c                 | 10 ++++++++--
+ 6 files changed, 34 insertions(+), 16 deletions(-)
+
 diff --git a/include/linux/security.h b/include/linux/security.h
-index 1bc00edd3a32..9b853796bd4f 100644
+index ca9485105f00..916a0f606035 100644
 --- a/include/linux/security.h
 +++ b/include/linux/security.h
-@@ -1985,25 +1985,27 @@ static inline void security_audit_rule_free(struct audit_lsm_rules *lsmrules)
- 
- #ifdef CONFIG_IMA_LSM_RULES
+@@ -1944,7 +1944,8 @@ static inline int security_key_getsecurity(struct key *key, char **_buffer)
  #ifdef CONFIG_SECURITY
--int ima_filter_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule);
--int ima_filter_rule_match(u32 secid, u32 field, u32 op, void *lsmrule);
--void ima_filter_rule_free(void *lsmrule);
-+int ima_filter_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule,
-+			 int lsmslot);
-+int ima_filter_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
-+			  int lsmslot);
-+void ima_filter_rule_free(void *lsmrule, int lsmslot);
+ 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
- 
- static inline int ima_filter_rule_init(u32 field, u32 op, char *rulestr,
--					   void **lsmrule)
-+					   void **lsmrule, int lsmslot)
- {
+@@ -1960,8 +1961,8 @@ static inline int security_audit_rule_known(struct audit_krule *krule)
  	return 0;
  }
  
- static inline int ima_filter_rule_match(u32 secid, u32 field, u32 op,
--					    void *lsmrule)
-+					    void *lsmrule, int lsmslot)
+-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;
  }
- 
--static inline void ima_filter_rule_free(void *lsmrule)
-+static inline void ima_filter_rule_free(void *lsmrule, int lsmslot)
- { }
- 
- #endif /* CONFIG_SECURITY */
+diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
+index a2340e81cfa7..6a04d762d272 100644
+--- a/kernel/auditfilter.c
++++ b/kernel/auditfilter.c
+@@ -1331,6 +1331,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:
+@@ -1362,8 +1363,9 @@ int audit_filter(int msgtype, unsigned int listtype)
+ 				if (f->lsm_isset) {
+ 					security_task_getsecid_subj(current,
+ 								    &sid);
+-					result = security_audit_rule_match(sid,
+-						   f->type, f->op,
++					lsmblob_init(&blob, sid);
++					result = security_audit_rule_match(
++						   &blob, f->type, f->op,
+ 						   f->lsm_rules);
+ 				}
+ 				break;
+diff --git a/kernel/auditsc.c b/kernel/auditsc.c
+index 392afe3e2fd6..71d894dcdc01 100644
+--- a/kernel/auditsc.c
++++ b/kernel/auditsc.c
+@@ -472,6 +472,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);
+@@ -670,8 +671,10 @@ static int audit_filter_rules(struct task_struct *tsk,
+ 					security_task_getsecid_subj(tsk, &sid);
+ 					need_sid = 0;
+ 				}
+-				result = security_audit_rule_match(sid, f->type,
+-							f->op, f->lsm_rules);
++				lsmblob_init(&blob, sid);
++				result = security_audit_rule_match(&blob,
++							f->type, f->op,
++							f->lsm_rules);
+ 			}
+ 			break;
+ 		case AUDIT_OBJ_USER:
+@@ -684,15 +687,17 @@ static int audit_filter_rules(struct task_struct *tsk,
+ 			if (f->lsm_isset) {
+ 				/* 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_rules);
+ 				} else if (ctx) {
+ 					list_for_each_entry(n, &ctx->names_list, list) {
++						lsmblob_init(&blob, name->osid);
+ 						if (security_audit_rule_match(
+-								n->osid,
++								&blob,
+ 								f->type,
+ 								f->op,
+ 								f->lsm_rules)) {
+@@ -704,7 +709,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_rules))
+ 					++result;
+diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
+index f0e448ed1f9f..55f3bd4f0b01 100644
+--- a/security/integrity/ima/ima.h
++++ b/security/integrity/ima/ima.h
+@@ -433,8 +433,8 @@ static inline void ima_filter_rule_free(void *lsmrule)
+ {
+ }
+ 
+-static inline int ima_filter_rule_match(u32 secid, u32 field, u32 op,
+-					void *lsmrule)
++static inline int ima_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 320ca80aacab..22952efcc0b0 100644
+index d804b9a0dd95..a05841e1012b 100644
 --- a/security/integrity/ima/ima_policy.c
 +++ b/security/integrity/ima/ima_policy.c
-@@ -90,6 +90,7 @@ struct ima_rule_entry {
- 	bool (*fgroup_op)(kgid_t cred_gid, kgid_t rule_gid); /* gid_eq(), gid_gt(), gid_lt() */
- 	int pcr;
- 	unsigned int allowed_algos; /* bitfield of allowed hash algorithms */
-+	int which;		/* which LSM rule applies to */
- 	struct {
- 		void *rule;	/* LSM file metadata specific */
- 		char *args_p;	/* audit value */
-@@ -286,6 +287,20 @@ static int __init default_appraise_policy_setup(char *str)
- }
- __setup("ima_appraise_tcb", default_appraise_policy_setup);
- 
-+static int ima_rules_lsm __ro_after_init;
-+
-+static int __init ima_rules_lsm_init(char *str)
-+{
-+	ima_rules_lsm = lsm_name_to_slot(str);
-+	if (ima_rules_lsm < 0) {
-+		ima_rules_lsm = 0;
-+		pr_err("rule lsm \"%s\" not registered", str);
-+	}
-+
-+	return 1;
-+}
-+__setup("ima_rules_lsm=", ima_rules_lsm_init);
-+
- static struct ima_rule_opt_list *ima_alloc_rule_opt_list(const substring_t *src)
- {
- 	struct ima_rule_opt_list *opt_list;
-@@ -357,7 +372,7 @@ static void ima_lsm_free_rule(struct ima_rule_entry *entry)
- 	int i;
- 
+@@ -607,6 +607,7 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
  	for (i = 0; i < MAX_LSM_RULES; i++) {
--		ima_filter_rule_free(entry->lsm[i].rule);
-+		ima_filter_rule_free(entry->lsm[i].rule, entry->which);
- 		kfree(entry->lsm[i].args_p);
- 	}
- }
-@@ -408,7 +423,8 @@ static struct ima_rule_entry *ima_lsm_copy_rule(struct ima_rule_entry *entry)
- 
- 		ima_filter_rule_init(nentry->lsm[i].type, Audit_equal,
- 				     nentry->lsm[i].args_p,
--				     &nentry->lsm[i].rule);
-+				     &nentry->lsm[i].rule,
-+				     entry->which);
- 		if (!nentry->lsm[i].rule)
- 			pr_warn("rule for LSM \'%s\' is undefined\n",
- 				nentry->lsm[i].args_p);
-@@ -624,14 +640,16 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
+ 		int rc = 0;
+ 		u32 osid;
++		struct lsmblob lsmdata;
+ 
+ 		if (!ima_lsm_isset(rule, i)) {
+ 			if (!rule->lsm[i].args_p)
+@@ -619,14 +620,16 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
+ 		case LSM_OBJ_ROLE:
+ 		case LSM_OBJ_TYPE:
  			security_inode_getsecid(inode, &osid);
- 			rc = ima_filter_rule_match(osid, rule->lsm[i].type,
+-			rc = ima_filter_rule_match(osid, rule->lsm[i].type,
++			lsmblob_init(&lsmdata, osid);
++			rc = ima_filter_rule_match(&lsmdata, rule->lsm[i].type,
  						   Audit_equal,
--						   rule->lsm[i].rule);
-+						   rule->lsm[i].rule,
-+						   rule->which);
+ 						   rule->lsm[i].rule);
  			break;
  		case LSM_SUBJ_USER:
  		case LSM_SUBJ_ROLE:
  		case LSM_SUBJ_TYPE:
- 			rc = ima_filter_rule_match(secid, rule->lsm[i].type,
+-			rc = ima_filter_rule_match(secid, rule->lsm[i].type,
++			lsmblob_init(&lsmdata, secid);
++			rc = ima_filter_rule_match(&lsmdata, rule->lsm[i].type,
  						   Audit_equal,
--						   rule->lsm[i].rule);
-+						   rule->lsm[i].rule,
-+						   rule->which);
+ 						   rule->lsm[i].rule);
  			break;
- 		default:
- 			break;
-@@ -1026,7 +1044,7 @@ enum policy_opt {
- 	Opt_fowner_lt, Opt_fgroup_lt,
- 	Opt_appraise_type, Opt_appraise_flag, Opt_appraise_algos,
- 	Opt_permit_directio, Opt_pcr, Opt_template, Opt_keyrings,
--	Opt_label, Opt_err
-+	Opt_lsm, Opt_label, Opt_err
- };
- 
- static const match_table_t policy_tokens = {
-@@ -1074,6 +1092,7 @@ static const match_table_t policy_tokens = {
- 	{Opt_template, "template=%s"},
- 	{Opt_keyrings, "keyrings=%s"},
- 	{Opt_label, "label=%s"},
-+	{Opt_lsm, "lsm=%s"},
- 	{Opt_err, NULL}
- };
- 
-@@ -1092,7 +1111,8 @@ static int ima_lsm_rule_init(struct ima_rule_entry *entry,
- 	entry->lsm[lsm_rule].type = audit_type;
- 	result = ima_filter_rule_init(entry->lsm[lsm_rule].type, Audit_equal,
- 				      entry->lsm[lsm_rule].args_p,
--				      &entry->lsm[lsm_rule].rule);
-+				      &entry->lsm[lsm_rule].rule,
-+				      entry->which);
- 	if (!entry->lsm[lsm_rule].rule) {
- 		pr_warn("rule for LSM \'%s\' is undefined\n",
- 			entry->lsm[lsm_rule].args_p);
-@@ -1781,6 +1801,19 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
- 						 &(template_desc->num_fields));
- 			entry->template = template_desc;
- 			break;
-+		case Opt_lsm:
-+			result = lsm_name_to_slot(args[0].from);
-+			if (result == LSMBLOB_INVALID) {
-+				int i;
-+
-+				for (i = 0; i < MAX_LSM_RULES; i++)
-+					entry->lsm[i].args_p = NULL;
-+				result = -EINVAL;
-+				break;
-+			}
-+			entry->which = result;
-+			result = 0;
-+			break;
- 		case Opt_err:
- 			ima_log_string(ab, "UNKNOWN", p);
- 			result = -EINVAL;
-@@ -1817,6 +1850,7 @@ ssize_t ima_parse_add_rule(char *rule)
- 	struct ima_rule_entry *entry;
- 	ssize_t result, len;
- 	int audit_info = 0;
-+	int i;
- 
- 	p = strsep(&rule, "\n");
- 	len = strlen(p) + 1;
-@@ -1834,6 +1868,9 @@ ssize_t ima_parse_add_rule(char *rule)
- 
- 	INIT_LIST_HEAD(&entry->list);
- 
-+	for (i = 0; i < MAX_LSM_RULES; i++)
-+		entry->which = ima_rules_lsm;
-+
- 	result = ima_parse_rule(p, entry);
- 	if (result) {
- 		ima_free_rule(entry);
-@@ -2151,6 +2188,8 @@ int ima_policy_show(struct seq_file *m, void *v)
- 		seq_puts(m, "appraise_flag=check_blacklist ");
- 	if (entry->flags & IMA_PERMIT_DIRECTIO)
- 		seq_puts(m, "permit_directio ");
-+	if (entry->which >= 0)
-+		seq_printf(m, pt(Opt_lsm), lsm_slot_to_name(entry->which));
- 	rcu_read_unlock();
- 	seq_puts(m, "\n");
- 	return 0;
 diff --git a/security/security.c b/security/security.c
-index 9f3a467fb992..580ef0c40be7 100644
+index 9471bcecc052..a5793b4bf684 100644
 --- a/security/security.c
 +++ b/security/security.c
-@@ -2705,19 +2705,42 @@ int security_audit_rule_match(u32 secid, u32 field, u32 op,
-  * The integrity subsystem uses the same hooks as
-  * the audit subsystem.
-  */
--int ima_filter_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule)
-+int ima_filter_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule,
-+			 int lsmslot)
- {
--	return call_int_hook(audit_rule_init, 0, field, op, rulestr, lsmrule);
-+	struct security_hook_list *hp;
-+
-+	hlist_for_each_entry(hp, &security_hook_heads.audit_rule_init, list)
-+		if (hp->lsmid->slot == lsmslot)
-+			return hp->hook.audit_rule_init(field, op, rulestr,
-+							lsmrule);
-+
-+	return 0;
- }
- 
--void ima_filter_rule_free(void *lsmrule)
-+void ima_filter_rule_free(void *lsmrule, int lsmslot)
- {
--	call_void_hook(audit_rule_free, lsmrule);
-+	struct security_hook_list *hp;
-+
-+	hlist_for_each_entry(hp, &security_hook_heads.audit_rule_free, list) {
-+		if (hp->lsmid->slot == lsmslot) {
-+			hp->hook.audit_rule_free(lsmrule);
-+			return;
-+		}
-+	}
- }
- 
--int ima_filter_rule_match(u32 secid, u32 field, u32 op, void *lsmrule)
-+int ima_filter_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
-+			  int lsmslot)
- {
--	return call_int_hook(audit_rule_match, 0, secid, field, op, lsmrule);
-+	struct security_hook_list *hp;
-+
-+	hlist_for_each_entry(hp, &security_hook_heads.audit_rule_match, list)
-+		if (hp->lsmid->slot == lsmslot)
-+			return hp->hook.audit_rule_match(secid, field, op,
-+							 lsmrule);
-+
-+	return 0;
- }
- #endif /* CONFIG_IMA_LSM_RULES */
- 
+@@ -2669,11 +2669,14 @@ void security_audit_rule_free(void **lsmrule)
+ 	hlist_for_each_entry(hp, &security_hook_heads.audit_rule_free, list) {
+ 		if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
+ 			continue;
++		if (lsmrule[hp->lsmid->slot] == NULL)
++			continue;
+ 		hp->hook.audit_rule_free(lsmrule[hp->lsmid->slot]);
+ 	}
+ }
+ 
+-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)
+ {
+ 	struct security_hook_list *hp;
+ 	int rc;
+@@ -2681,7 +2684,10 @@ int security_audit_rule_match(u32 secid, u32 field, u32 op, void **lsmrule)
+ 	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(secid, field, op,
++		if (lsmrule[hp->lsmid->slot] == NULL)
++			continue;
++		rc = hp->hook.audit_rule_match(blob->secid[hp->lsmid->slot],
++					       field, op,
+ 					       &lsmrule[hp->lsmid->slot]);
+ 		if (rc)
+ 			return rc;
 -- 
-2.31.1
-
+2.29.2
+
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help