[RFC,04/30] ima: Add ima policy related data to the ima namespace

Submitted by krzysztof.struczynski@huawei.com on Aug. 18, 2020, 3:20 p.m.

Details

Message ID 20200818152037.11869-5-krzysztof.struczynski@huawei.com
State New
Series "Series without cover letter"
Headers show

Commit Message

krzysztof.struczynski@huawei.com Aug. 18, 2020, 3:20 p.m.
From: Krzysztof Struczynski <krzysztof.struczynski@huawei.com>

Collate global variables describing the ima policy in one structure and
add it to the ima namespace. Collate setup data (parsed kernel boot
parameters) in a separate structure.

Per namespace policy is not yet properly set and it is not used. This
will be done in the following patches.

Signed-off-by: Krzysztof Struczynski <krzysztof.struczynski@huawei.com>
---
 include/linux/ima.h                 |  2 ++
 security/integrity/ima/ima.h        | 24 +++++++++++++++++
 security/integrity/ima/ima_init.c   |  3 ++-
 security/integrity/ima/ima_ns.c     | 41 +++++++++++++++++++++++++++--
 security/integrity/ima/ima_policy.c | 26 ++++++++++++++++++
 5 files changed, 93 insertions(+), 3 deletions(-)

Patch hide | download patch | download mbox

diff --git a/include/linux/ima.h b/include/linux/ima.h
index 3954cef57c00..d61c9c21ffb9 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -16,6 +16,7 @@  struct nsproxy;
 struct task_struct;
 struct list_head;
 struct llist_node;
+struct ima_policy_data;
 
 #ifdef CONFIG_IMA
 extern int ima_bprm_check(struct linux_binprm *bprm);
@@ -188,6 +189,7 @@  struct ima_namespace {
 	struct llist_node cleanup_list; /* namespaces on a death row */
 	atomic_t inactive; /* set only when ns is added to the cleanup list */
 	bool frozen;
+	struct ima_policy_data *policy_data;
 } __randomize_layout;
 
 extern struct ima_namespace init_ima_ns;
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 092e87190c6d..0d88222e3500 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -60,6 +60,14 @@  extern int ima_appraise;
 extern struct tpm_chip *ima_tpm_chip;
 extern const char boot_aggregate_name[];
 
+/* IMA policy setup data */
+struct ima_policy_setup_data {
+	int ima_policy;
+	int ima_appraise;
+	bool ima_use_secure_boot;
+	bool ima_use_appraise_tcb;
+};
+
 /* IMA event related data */
 struct ima_event_data {
 	struct integrity_iint_cache *iint;
@@ -286,6 +294,8 @@  int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
 		     struct ima_template_desc **template_desc,
 		     const char *keyring);
 void ima_init_policy(void);
+void ima_init_ns_policy(struct ima_namespace *ima_ns,
+			const struct ima_policy_setup_data *policy_setup_data);
 void ima_update_policy(void);
 void ima_update_policy_flag(void);
 ssize_t ima_parse_add_rule(char *);
@@ -372,6 +382,20 @@  static inline int ima_read_xattr(struct dentry *dentry,
 
 #endif /* CONFIG_IMA_APPRAISE */
 
+struct ima_policy_data {
+	struct list_head ima_default_rules;
+	struct list_head ima_policy_rules;
+	struct list_head ima_temp_rules;
+	struct list_head *ima_rules;
+	bool ima_fail_unverifiable_sigs;
+	int ima_policy_flag; /* current content of the policy */
+	int ima_appraise;
+	int temp_ima_appraise;
+};
+
+extern struct ima_policy_data init_policy_data;
+extern struct ima_policy_setup_data init_policy_setup_data;
+
 extern struct list_head ima_ns_list;
 extern struct rw_semaphore ima_ns_list_lock;
 
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
index 0ba04a1a68cc..ea5ff42eb7fe 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -32,7 +32,8 @@  struct ima_namespace init_ima_ns = {
 #ifdef CONFIG_IMA_NS
 	.ns.ops = &imans_operations,
 #endif
-	.frozen = true
+	.frozen = true,
+	.policy_data = &init_policy_data,
 };
 EXPORT_SYMBOL(init_ima_ns);
 
diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c
index 3a98cd536d05..1aeb9cfeb3a2 100644
--- a/security/integrity/ima/ima_ns.c
+++ b/security/integrity/ima/ima_ns.c
@@ -51,9 +51,38 @@  static struct ima_namespace *ima_ns_alloc(void)
 
 	ima_ns = kzalloc(sizeof(*ima_ns), GFP_KERNEL);
 	if (!ima_ns)
-		return NULL;
+		goto out;
+
+	ima_ns->policy_data = kzalloc(sizeof(struct ima_policy_data),
+				      GFP_KERNEL);
+	if (!ima_ns->policy_data)
+		goto out_free;
 
 	return ima_ns;
+
+out_free:
+	kfree(ima_ns);
+out:
+	return NULL;
+}
+
+static void ima_set_ns_policy(struct ima_namespace *ima_ns,
+			      char *policy_setup_str)
+{
+	struct ima_policy_setup_data setup_data;
+
+#ifdef CONFIG_IMA_APPRAISE
+	setup_data.ima_appraise = IMA_APPRAISE_ENFORCE;
+#endif
+	/* Configuring IMA namespace will be implemented in the following
+	 * patches. When it is done, parse configuration string and store result
+	 * in setup_data. Temporarily use init_policy_setup_data.
+	 */
+	setup_data = init_policy_setup_data;
+	ima_ns->policy_data->ima_fail_unverifiable_sigs =
+		init_ima_ns.policy_data->ima_fail_unverifiable_sigs;
+
+	ima_init_ns_policy(ima_ns, &setup_data);
 }
 
 /**
@@ -64,7 +93,7 @@  static struct ima_namespace *ima_ns_alloc(void)
  * Return:	ERR_PTR(-ENOMEM) on error (failure to kmalloc), new ns otherwise
  */
 static struct ima_namespace *clone_ima_ns(struct user_namespace *user_ns,
-					   struct ima_namespace *old_ns)
+					  struct ima_namespace *old_ns)
 {
 	struct ima_namespace *ns;
 	struct ucounts *ucounts;
@@ -91,9 +120,14 @@  static struct ima_namespace *clone_ima_ns(struct user_namespace *user_ns,
 	ns->ucounts = ucounts;
 	ns->frozen = false;
 
+	INIT_LIST_HEAD(&ns->policy_data->ima_default_rules);
+	INIT_LIST_HEAD(&ns->policy_data->ima_policy_rules);
+	INIT_LIST_HEAD(&ns->policy_data->ima_temp_rules);
+
 	return ns;
 
 fail_free:
+	kfree(ns->policy_data);
 	kfree(ns);
 fail_dec:
 	dec_ima_namespaces(ucounts);
@@ -139,6 +173,7 @@  static void destroy_ima_ns(struct ima_namespace *ns)
 	dec_ima_namespaces(ns->ucounts);
 	put_user_ns(ns->user_ns);
 	ns_free_inum(&ns->ns);
+	kfree(ns->policy_data);
 	kfree(ns);
 }
 
@@ -238,6 +273,8 @@  static int imans_activate(struct ima_namespace *ima_ns)
 	if (ima_ns->frozen)
 		goto out;
 
+	ima_set_ns_policy(ima_ns, NULL);
+
 	ima_ns->frozen = true;
 
 	down_write(&ima_ns_list_lock);
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 07f033634b27..6b56741ec1c9 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -212,6 +212,17 @@  static size_t ima_keyrings_len;
 
 static int ima_policy __initdata;
 
+struct ima_policy_setup_data init_policy_setup_data = {
+#ifdef CONFIG_IMA_APPRAISE
+	.ima_appraise = IMA_APPRAISE_ENFORCE,
+#endif
+};
+struct ima_policy_data init_policy_data = {
+	.ima_default_rules = LIST_HEAD_INIT(init_policy_data.ima_default_rules),
+	.ima_policy_rules = LIST_HEAD_INIT(init_policy_data.ima_policy_rules),
+	.ima_temp_rules = LIST_HEAD_INIT(init_policy_data.ima_temp_rules),
+};
+
 static int __init default_measure_policy_setup(char *str)
 {
 	if (ima_policy)
@@ -715,6 +726,21 @@  static int __init ima_init_arch_policy(void)
 	return i;
 }
 
+/**
+ * ima_init_ns_policy - initialize the default measure rules.
+ * @ima_ns: pointer to the namespace whose rules are being initialized
+ * @setup_data: pointer to the policy setup data
+ */
+void ima_init_ns_policy(struct ima_namespace *ima_ns,
+			const struct ima_policy_setup_data *setup_data)
+{
+	/* Set policy rules to the empty set of default rules. The rest will be
+	 * implemented after namespacing policy.
+	 */
+	ima_ns->policy_data->ima_rules =
+		&ima_ns->policy_data->ima_default_rules;
+}
+
 /**
  * ima_init_policy - initialize the default measure rules.
  *