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

From: krzysztof.struczynski
Date: Tue Aug 18 2020 - 11:49:55 EST


From: Krzysztof Struczynski <krzysztof.struczynski@xxxxxxxxxx>

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@xxxxxxxxxx>
---
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