[RFC PATCH 26/30] ima: Add key domain to the ima namespace
From: <hidden>
Date: 2020-08-18 15:49:55
Also in:
linux-integrity, lkml
Subsystem:
extended verification module (evm), integrity measurement architecture (ima), keys/keyrings, security subsystem, the rest · Maintainers:
Mimi Zohar, Roberto Sassu, Dmitry Kasatkin, David Howells, Jarkko Sakkinen, Paul Moore, James Morris, "Serge E. Hallyn", Linus Torvalds
From: Krzysztof Struczynski <redacted> 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 <redacted> --- 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