@@ -49,11 +49,19 @@ extern int ima_policy_flag;
/* bitset of digests algorithms allowed in the setxattr hook */
extern atomic_t ima_setxattr_allowed_hash_algorithms;
+/* IMA hash algorithm description */
+struct ima_algo_desc {
+ struct crypto_shash *tfm;
+ enum hash_algo algo;
+};
+
/* set during initialization */
extern int ima_hash_algo __ro_after_init;
extern int ima_sha1_idx __ro_after_init;
extern int ima_hash_algo_idx __ro_after_init;
extern int ima_extra_slots __ro_after_init;
+extern struct ima_algo_desc *ima_algo_array __ro_after_init;
+
extern int ima_appraise;
extern struct tpm_chip *ima_tpm_chip;
extern const char boot_aggregate_name[];
@@ -57,11 +57,6 @@ MODULE_PARM_DESC(ahash_bufsize, "Maximum ahash buffer size");
static struct crypto_shash *ima_shash_tfm;
static struct crypto_ahash *ima_ahash_tfm;
-struct ima_algo_desc {
- struct crypto_shash *tfm;
- enum hash_algo algo;
-};
-
int ima_sha1_idx __ro_after_init;
int ima_hash_algo_idx __ro_after_init;
/*
@@ -70,7 +65,7 @@ int ima_hash_algo_idx __ro_after_init;
*/
int ima_extra_slots __ro_after_init;
-static struct ima_algo_desc *ima_algo_array;
+struct ima_algo_desc *ima_algo_array __ro_after_init;
static int __init ima_init_ima_crypto(void)
{
@@ -116,9 +116,31 @@ void ima_putc(struct seq_file *m, void *data, int datalen)
seq_putc(m, *(char *)data++);
}
+static struct dentry **ascii_securityfs_measurement_lists __ro_after_init;
+static struct dentry **binary_securityfs_measurement_lists __ro_after_init;
+static int securityfs_measurement_list_count __ro_after_init;
+
+static void lookup_template_data_hash_algo(int *algo_idx, enum hash_algo *algo,
+ struct seq_file *m,
+ struct dentry **lists)
+{
+ struct dentry *dentry;
+ int i;
+
+ dentry = file_dentry(m->file);
+
+ for (i = 0; i < securityfs_measurement_list_count; i++) {
+ if (dentry == lists[i]) {
+ *algo_idx = i;
+ *algo = ima_algo_array[i].algo;
+ break;
+ }
+ }
+}
+
/* print format:
* 32bit-le=pcr#
- * char[20]=template digest
+ * char[n]=template digest
* 32bit-le=template name size
* char[n]=template name
* [eventdata length]
@@ -132,7 +154,15 @@ int ima_measurements_show(struct seq_file *m, void *v)
char *template_name;
u32 pcr, namelen, template_data_len; /* temporary fields */
bool is_ima_template = false;
- int i;
+ enum hash_algo algo;
+ int i, algo_idx;
+
+ algo_idx = ima_sha1_idx;
+ algo = HASH_ALGO_SHA1;
+
+ if (m->file != NULL)
+ lookup_template_data_hash_algo(&algo_idx, &algo, m,
+ binary_securityfs_measurement_lists);
/* get entry */
e = qe->entry;
@@ -151,7 +181,7 @@ int ima_measurements_show(struct seq_file *m, void *v)
ima_putc(m, &pcr, sizeof(e->pcr));
/* 2nd: template digest */
- ima_putc(m, e->digests[ima_sha1_idx].digest, TPM_DIGEST_SIZE);
+ ima_putc(m, e->digests[algo_idx].digest, hash_digest_size[algo]);
/* 3rd: template name size */
namelen = !ima_canonical_fmt ? strlen(template_name) :
@@ -220,7 +250,15 @@ static int ima_ascii_measurements_show(struct seq_file *m, void *v)
struct ima_queue_entry *qe = v;
struct ima_template_entry *e;
char *template_name;
- int i;
+ enum hash_algo algo;
+ int i, algo_idx;
+
+ algo_idx = ima_sha1_idx;
+ algo = HASH_ALGO_SHA1;
+
+ if (m->file != NULL)
+ lookup_template_data_hash_algo(&algo_idx, &algo, m,
+ ascii_securityfs_measurement_lists);
/* get entry */
e = qe->entry;
@@ -233,8 +271,8 @@ static int ima_ascii_measurements_show(struct seq_file *m, void *v)
/* 1st: PCR used (config option) */
seq_printf(m, "%2d ", e->pcr);
- /* 2nd: SHA1 template hash */
- ima_print_digest(m, e->digests[ima_sha1_idx].digest, TPM_DIGEST_SIZE);
+ /* 2nd: template hash */
+ ima_print_digest(m, e->digests[algo_idx].digest, hash_digest_size[algo]);
/* 3th: template name */
seq_printf(m, " %s", template_name);
@@ -379,6 +417,71 @@ static const struct seq_operations ima_policy_seqops = {
};
#endif
+static void __init remove_securityfs_measurement_lists(struct dentry **lists)
+{
+ int i;
+
+ if (lists) {
+ for (i = 0; i < securityfs_measurement_list_count; i++)
+ securityfs_remove(lists[i]);
+
+ kfree(lists);
+ }
+
+ securityfs_measurement_list_count = 0;
+}
+
+static int __init create_securityfs_measurement_lists(void)
+{
+ char file_name[NAME_MAX + 1];
+ struct dentry *dentry;
+ u16 algo;
+ int i;
+
+ securityfs_measurement_list_count = NR_BANKS(ima_tpm_chip);
+
+ if (ima_sha1_idx >= NR_BANKS(ima_tpm_chip))
+ securityfs_measurement_list_count++;
+
+ ascii_securityfs_measurement_lists =
+ kcalloc(securityfs_measurement_list_count, sizeof(struct dentry *),
+ GFP_KERNEL);
+ if (!ascii_securityfs_measurement_lists)
+ return -ENOMEM;
+
+ binary_securityfs_measurement_lists =
+ kcalloc(securityfs_measurement_list_count, sizeof(struct dentry *),
+ GFP_KERNEL);
+ if (!binary_securityfs_measurement_lists)
+ return -ENOMEM;
+
+ for (i = 0; i < securityfs_measurement_list_count; i++) {
+ algo = ima_algo_array[i].algo;
+
+ sprintf(file_name, "ascii_runtime_measurements_%s",
+ hash_algo_name[algo]);
+ dentry = securityfs_create_file(file_name, S_IRUSR | S_IRGRP,
+ ima_dir, NULL,
+ &ima_ascii_measurements_ops);
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
+
+ ascii_securityfs_measurement_lists[i] = dentry;
+
+ sprintf(file_name, "binary_runtime_measurements_%s",
+ hash_algo_name[algo]);
+ dentry = securityfs_create_file(file_name, S_IRUSR | S_IRGRP,
+ ima_dir, NULL,
+ &ima_measurements_ops);
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
+
+ binary_securityfs_measurement_lists[i] = dentry;
+ }
+
+ return 0;
+}
+
/*
* ima_open_policy: sequentialize access to the policy file
*/
@@ -454,6 +557,9 @@ int __init ima_fs_init(void)
{
int ret;
+ ascii_securityfs_measurement_lists = NULL;
+ binary_securityfs_measurement_lists = NULL;
+
ima_dir = securityfs_create_dir("ima", integrity_dir);
if (IS_ERR(ima_dir))
return PTR_ERR(ima_dir);
@@ -465,19 +571,21 @@ int __init ima_fs_init(void)
goto out;
}
+ ret = create_securityfs_measurement_lists();
+ if (ret != 0)
+ goto out;
+
binary_runtime_measurements =
- securityfs_create_file("binary_runtime_measurements",
- S_IRUSR | S_IRGRP, ima_dir, NULL,
- &ima_measurements_ops);
+ securityfs_create_symlink("binary_runtime_measurements", ima_dir,
+ "binary_runtime_measurements_sha1", NULL);
if (IS_ERR(binary_runtime_measurements)) {
ret = PTR_ERR(binary_runtime_measurements);
goto out;
}
ascii_runtime_measurements =
- securityfs_create_file("ascii_runtime_measurements",
- S_IRUSR | S_IRGRP, ima_dir, NULL,
- &ima_ascii_measurements_ops);
+ securityfs_create_symlink("ascii_runtime_measurements", ima_dir,
+ "ascii_runtime_measurements_sha1", NULL);
if (IS_ERR(ascii_runtime_measurements)) {
ret = PTR_ERR(ascii_runtime_measurements);
goto out;
@@ -515,6 +623,8 @@ int __init ima_fs_init(void)
securityfs_remove(runtime_measurements_count);
securityfs_remove(ascii_runtime_measurements);
securityfs_remove(binary_runtime_measurements);
+ remove_securityfs_measurement_lists(ascii_securityfs_measurement_lists);
+ remove_securityfs_measurement_lists(binary_securityfs_measurement_lists);
securityfs_remove(ima_symlink);
securityfs_remove(ima_dir);
@@ -30,6 +30,7 @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
goto out;
}
+ file.file = NULL;
file.size = segment_size;
file.read_pos = 0;
file.count = sizeof(khdr); /* reserved space */