[RFC,26/30] ima: Add key domain to the ima namespace

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

Details

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

Commit Message

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

Add key domain to the ima namespace. This will allow to bind the
appraisal keys with the namespace and store all appraisal keys in the
ima system keyring.

Signed-off-by: Krzysztof Struczynski <krzysztof.struczynski@huawei.com>
---
 include/linux/ima.h               |  3 +++
 security/integrity/ima/ima_init.c |  8 ++++++++
 security/integrity/ima/ima_ns.c   | 14 ++++++++++++++
 security/keys/key.c               | 10 +++++++---
 4 files changed, 32 insertions(+), 3 deletions(-)

Patch hide | download patch | download mbox

diff --git a/include/linux/ima.h b/include/linux/ima.h
index 158028834747..7db4995c66cf 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -208,6 +208,9 @@  struct ima_namespace {
 	char *policy_path_for_children;
 	char *x509_path_for_children;
 	struct ima_policy_setup_data *policy_setup_for_children;
+#ifdef CONFIG_KEYS
+	struct key_tag *key_domain;
+#endif
 } __randomize_layout;
 
 extern struct ima_namespace init_ima_ns;
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
index d14c6689f422..1668edf3ed32 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -18,6 +18,7 @@ 
 #include <linux/kref.h>
 #include <linux/proc_ns.h>
 #include <linux/user_namespace.h>
+#include <linux/key.h>
 
 #include "ima.h"
 
@@ -25,6 +26,10 @@ 
 const char boot_aggregate_name[] = "boot_aggregate";
 struct tpm_chip *ima_tpm_chip;
 
+#ifdef CONFIG_KEYS
+static struct key_tag init_ima_key_domain = { .usage = REFCOUNT_INIT(1) };
+#endif
+
 struct ima_namespace init_ima_ns = {
 	.kref = KREF_INIT(2),
 	.user_ns = &init_user_ns,
@@ -41,6 +46,9 @@  struct ima_namespace init_ima_ns = {
 	.measurements = &ima_measurements,
 	.ml_len = ATOMIC_LONG_INIT(0),
 	.violations = ATOMIC_LONG_INIT(0),
+#ifdef CONFIG_KEYS
+	.key_domain = &init_ima_key_domain,
+#endif
 };
 EXPORT_SYMBOL(init_ima_ns);
 
diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c
index ec3abc803c82..872dc6a96a96 100644
--- a/security/integrity/ima/ima_ns.c
+++ b/security/integrity/ima/ima_ns.c
@@ -28,6 +28,7 @@ 
 #include <linux/mutex.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <linux/key.h>
 
 #include "ima.h"
 
@@ -65,8 +66,16 @@  static struct ima_namespace *ima_ns_alloc(void)
 	if (!ima_ns->iint_tree)
 		goto policy_free;
 
+#ifdef CONFIG_KEYS
+	ima_ns->key_domain = kzalloc(sizeof(struct key_tag), GFP_KERNEL);
+	if (!ima_ns->key_domain)
+		goto iint_free;
+#endif
+
 	return ima_ns;
 
+iint_free:
+	kfree(ima_ns->iint_tree);
 policy_free:
 	kfree(ima_ns->policy_data);
 ns_free:
@@ -171,6 +180,9 @@  static struct ima_namespace *clone_ima_ns(struct user_namespace *user_ns,
 	rwlock_init(&ns->iint_tree->lock);
 	ns->iint_tree->root = RB_ROOT;
 
+#ifdef CONFIG_KEYS
+	refcount_set(&ns->key_domain->usage, 1);
+#endif
 	ns->policy_path_for_children = NULL;
 	ns->x509_path_for_children = NULL;
 	ns->policy_setup_for_children = NULL;
@@ -184,6 +196,7 @@  static struct ima_namespace *clone_ima_ns(struct user_namespace *user_ns,
 fail_free:
 	kfree(ns->iint_tree);
 	kfree(ns->policy_data);
+	kfree(ns->key_domain);
 	kfree(ns);
 fail_dec:
 	dec_ima_namespaces(ucounts);
@@ -239,6 +252,7 @@  static void destroy_ima_ns(struct ima_namespace *ns)
 	bool is_init_ns = (ns == &init_ima_ns);
 
 	dec_ima_namespaces(ns->ucounts);
+	key_remove_domain(ns->key_domain);
 	put_user_ns(ns->user_ns);
 	ns_free_inum(&ns->ns);
 	integrity_iint_tree_free(ns->iint_tree);
diff --git a/security/keys/key.c b/security/keys/key.c
index 1b0183d33bbc..fca0d12f5c71 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -285,10 +285,14 @@  struct key *key_alloc(struct key_type *type, const char *desc,
 
 		/* set domain tag if it's not predefined for the key type */
 		if ((!type->flags) && (flags & KEY_ALLOC_DOMAIN_IMA))
-			/* Set it to something meaningful after adding a key
-			 * domain to the ima namespace.
+			/* Use ima_ns_for_children, not ima_ns. ima_ns_for
+			 * children is equal to ima_ns, unless ima namespace was
+			 * unshared and the new namespace is being configured.
+			 * In that case, new keys should be associated with the
+			 * new ima namespace.
 			 */
-			key->index_key.domain_tag = NULL;
+			key->index_key.domain_tag =
+				current->nsproxy->ima_ns_for_children->key_domain;
 	}
 
 	key->index_key.desc_len = desclen;