From: Krzysztof Struczynski <[email protected]>

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 <[email protected]>
---
 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(-)

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;
-- 
2.20.1

Reply via email to