From: Krzysztof Struczynski krzysztof.struczynski@huawei.com
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I49KW1 CVE: NA
--------------------------------
Maintain per ima namespace measurement list. It will be used to provide information about the namespace measurements in securityfs and to clean up hash table entries when the namespace is destroyed.
The global measurement list remains and is not modified. It is necessary to keep it so that the PCR value can be recreated.
Signed-off-by: Krzysztof Struczynski krzysztof.struczynski@huawei.com Reviewed-by: Zhang Tianxing zhangtianxing3@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/ima.h | 1 + security/integrity/ima/ima.h | 7 +++++-- security/integrity/ima/ima_api.c | 12 +++++++----- security/integrity/ima/ima_init.c | 4 +++- security/integrity/ima/ima_main.c | 3 ++- security/integrity/ima/ima_ns.c | 1 + security/integrity/ima/ima_queue.c | 11 +++++++---- 7 files changed, 26 insertions(+), 13 deletions(-)
diff --git a/include/linux/ima.h b/include/linux/ima.h index d7b2864d7d7c..0ab1dbf34c47 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 324ccfbbc1dc..6e7a5cf253cc 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 2678faaa7a15..6724ee072cd9 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 52b675d47177..00c8dfea6ba8 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 18291787dbb5..673091d612de 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 04aa50473971..a6197c708f3a 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 c096ef8945c7..673fd95c8d33 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; }