diff --git a/include/linux/ima.h b/include/linux/ima.h index d7b2864d7d7c2cbd611f095c818c2cefedac8ee6..0ab1dbf34c47ab731c1a6831928cf1fefb71d5d2 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -232,6 +232,7 @@ struct ima_namespace { bool frozen; struct ima_policy_data *policy_data; struct integrity_iint_tree *iint_tree; + struct list_head ns_measurements; } __randomize_layout; extern struct ima_namespace init_ima_ns; diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 324ccfbbc1dc3bb06b938b7f221136d2d7e85621..6e7a5cf253cc6a933cb0f57fb2f9b719716cbab3 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -119,6 +119,7 @@ struct ima_template_entry { struct ima_queue_entry { struct hlist_node hnext; /* place in hash collision list */ struct list_head later; /* place in ima_measurements list */ + struct list_head ns_later; /* place in ima namespace list */ struct ima_template_entry *entry; }; extern struct list_head ima_measurements; /* list of all measurements */ @@ -151,7 +152,8 @@ int ima_init(void); int ima_fs_init(void); int ima_add_template_entry(struct ima_template_entry *entry, int violation, const char *op, struct inode *inode, - const unsigned char *filename); + const unsigned char *filename, + struct ima_namespace *ima_ns); int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash); int ima_calc_buffer_hash(const void *buf, loff_t len, struct ima_digest_data *hash); @@ -293,7 +295,8 @@ int ima_alloc_init_template(struct ima_event_data *event_data, struct ima_template_desc *template_desc); int ima_store_template(struct ima_template_entry *entry, int violation, struct inode *inode, const unsigned char *filename, - int pcr, struct ima_digest *digest); + int pcr, struct ima_digest *digest, + struct ima_namespace *ima_ns); void ima_free_template_entry(struct ima_template_entry *entry); const char *ima_d_path(const struct path *path, char **pathbuf, char *filename); diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 2678faaa7a15d55185ad20146067e83ff2cdce0e..6724ee072cd951a4b8d95b1b63cc389c55d84681 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -104,7 +104,8 @@ int ima_alloc_init_template(struct ima_event_data *event_data, int ima_store_template(struct ima_template_entry *entry, int violation, struct inode *inode, const unsigned char *filename, int pcr, - struct ima_digest *digest) + struct ima_digest *digest, + struct ima_namespace *ima_ns) { static const char op[] = "add_template_measure"; static const char audit_cause[] = "hashing_error"; @@ -134,10 +135,11 @@ int ima_store_template(struct ima_template_entry *entry, } entry->pcr = pcr; - result = ima_add_template_entry(entry, violation, op, inode, filename); + result = ima_add_template_entry(entry, violation, op, inode, filename, + ima_ns); if (!result && duplicated_entry) { result = ima_add_template_entry(duplicated_entry, violation, op, - inode, filename); + inode, filename, ima_ns); if (result < 0) kfree(duplicated_entry); } @@ -177,7 +179,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename, goto err_out; } result = ima_store_template(entry, violation, inode, filename, - CONFIG_IMA_MEASURE_PCR_IDX, NULL); + CONFIG_IMA_MEASURE_PCR_IDX, NULL, ima_ns); if (result < 0) ima_free_template_entry(entry); err_out: @@ -364,7 +366,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint, } result = ima_store_template(entry, violation, inode, filename, pcr, - digest); + digest, ima_ns); out: if ((!result || result == -EEXIST) && !(file->f_flags & O_DIRECT)) { iint->flags |= IMA_MEASURED; diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 52b675d47177b44aa48ed76b014272edbaec17d6..00c8dfea6ba8691bbb310e911c92fb3b2a10f7a0 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -35,6 +35,7 @@ struct ima_namespace init_ima_ns = { .frozen = true, .policy_data = &init_policy_data, .iint_tree = &init_iint_tree, + .ns_measurements = LIST_HEAD_INIT(init_ima_ns.ns_measurements), }; EXPORT_SYMBOL(init_ima_ns); @@ -104,7 +105,8 @@ static int __init ima_add_boot_aggregate(void) result = ima_store_template(entry, violation, NULL, boot_aggregate_name, - CONFIG_IMA_MEASURE_PCR_IDX, NULL); + CONFIG_IMA_MEASURE_PCR_IDX, NULL, + &init_ima_ns); if (result < 0) { ima_free_template_entry(entry); audit_cause = "store_entry"; diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 18291787dbb56b91423deac1c2ca9024ef9800ab..673091d612dec1d7b9d95b4fa26f3615bdbb88e2 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -1075,7 +1075,8 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size, goto out; } - ret = ima_store_template(entry, violation, NULL, buf, pcr, NULL); + ret = ima_store_template(entry, violation, NULL, buf, pcr, NULL, + ima_ns); if (ret < 0) { audit_cause = "store_entry"; ima_free_template_entry(entry); diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index 04aa50473971ccd9d4ed46f40ff2e8510a3bbe7f..a6197c708f3a0a05ba40a11dc6463866a7e20195 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -130,6 +130,7 @@ static struct ima_namespace *clone_ima_ns(struct user_namespace *user_ns, rwlock_init(&ns->iint_tree->lock); ns->iint_tree->root = RB_ROOT; + INIT_LIST_HEAD(&ns->ns_measurements); INIT_LIST_HEAD(&ns->policy_data->ima_default_rules); INIT_LIST_HEAD(&ns->policy_data->ima_policy_rules); INIT_LIST_HEAD(&ns->policy_data->ima_temp_rules); diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index c096ef8945c7d0a9743de258cee1cd8d48bebaa5..673fd95c8d33af2bc6b4eee30d60eede5672b5b4 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -91,7 +91,8 @@ static int get_binary_runtime_size(struct ima_template_entry *entry) * (Called with ima_extend_list_mutex held.) */ static int ima_add_digest_entry(struct ima_template_entry *entry, - bool update_htable) + bool update_htable, + struct ima_namespace *ima_ns) { struct ima_queue_entry *qe; unsigned int key; @@ -105,6 +106,7 @@ static int ima_add_digest_entry(struct ima_template_entry *entry, INIT_LIST_HEAD(&qe->later); list_add_tail_rcu(&qe->later, &ima_measurements); + list_add_tail_rcu(&qe->ns_later, &ima_ns->ns_measurements); atomic_long_inc(&ima_htable.len); if (update_htable) { @@ -158,7 +160,8 @@ static int ima_pcr_extend(struct tpm_digest *digests_arg, int pcr) */ int ima_add_template_entry(struct ima_template_entry *entry, int violation, const char *op, struct inode *inode, - const unsigned char *filename) + const unsigned char *filename, + struct ima_namespace *ima_ns) { u8 *digest = entry->digests[ima_hash_algo_idx].digest; struct tpm_digest *digests_arg = entry->digests; @@ -176,7 +179,7 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation, } } - result = ima_add_digest_entry(entry, 1); + result = ima_add_digest_entry(entry, 1, ima_ns); if (result < 0) { audit_cause = "ENOMEM"; audit_info = 0; @@ -205,7 +208,7 @@ int ima_restore_measurement_entry(struct ima_template_entry *entry) int result = 0; mutex_lock(&ima_extend_list_mutex); - result = ima_add_digest_entry(entry, 0); + result = ima_add_digest_entry(entry, 0, &init_ima_ns); mutex_unlock(&ima_extend_list_mutex); return result; }