diff --git a/include/linux/ima.h b/include/linux/ima.h index 1270337c1d99f44c64392af032d206c9709815b4..eb022229c694982458a947a4522d096ddfb92f2f 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -237,6 +237,9 @@ struct ima_namespace { atomic_long_t violations; 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 7a0a640fdf9c0a73ef5a395cabbcb25a1880d507..73fb0f0e82c5a76fb39961c3d3a5ac2924d46cf5 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -18,6 +18,7 @@ #include #include #include +#include #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, @@ -40,6 +45,9 @@ struct ima_namespace init_ima_ns = { .ns_measurements = LIST_HEAD_INIT(init_ima_ns.ns_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 57dc9fedb8fdb5f7eabe3fa9e85801bf6ee42abd..639e5eadee31196a36f609c54b2b99a9246edb63 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "ima.h" @@ -66,8 +67,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: @@ -147,6 +156,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->x509_path_for_children = NULL; ns->policy_setup_for_children = NULL; @@ -160,6 +172,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); @@ -231,6 +244,7 @@ static void destroy_ima_ns(struct ima_namespace *ns) imans_remove_hash_entries(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 d052b9a0b1fdb3719b42029368993a454ca3f2c5..43de2dfe95cfebae076a2c4c9f7de6dbb1579fa8 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;