diff mbox series

[v2] ima: add crypto agility support for template-hash algorithm

Message ID 20240121161633.2302285-1-enrico.bravi@polito.it (mailing list archive)
State New, archived
Headers show
Series [v2] ima: add crypto agility support for template-hash algorithm | expand

Commit Message

Enrico Bravi Jan. 21, 2024, 4:16 p.m. UTC
The template hash showed by the ascii_runtime_measurements and
binary_runtime_measurements is the one calculated using sha1 and there is no
possibility to change this value, despite the fact that the template hash is
calculated using the hash algorothms corresponding to all the PCR banks
configured in the TPM.

This patch introduce the support to retrieve the ima log with the template data
hash calculated with a specific hash algorithm.
Add a new file in the securityfs ima directory for each hash algo configured
for the PCR banks of the TPM. Each new file has the name with the following
structure:

	{binary, ascii}_runtime_measurements_<hash_algo_name>

except for sha1 which it remains associated with the standard file names.
The <hash_algo_name> is used to select the template data hash algorithm to show
in ima_ascii_measurements_show() and in ima_measurements_show().

As example, in the case sha1 and sha256 are the configured PCR banks, the
listing of the security/ima directory is the following:

-r--r----- 1 root root 0 gen 20 15:06 ascii_runtime_measurements
-r--r----- 1 root root 0 gen 20 15:06 ascii_runtime_measurements_sha256
-r--r----- 1 root root 0 gen 20 15:06 binary_runtime_measurements
-r--r----- 1 root root 0 gen 20 15:06 binary_runtime_measurements_sha256
--w------- 1 root root 0 gen 20 15:06 policy
-r--r----- 1 root root 0 gen 20 15:06 runtime_measurements_count
-r--r----- 1 root root 0 gen 20 15:06 violations

v2:
 - Changed the behaviour of configuring at boot time the template data hash
   algorithm.
 - Removed template data hash algo name prefix.
 - Removed ima_template_hash command line option.
 - Introducing a new file in the securityfs ima subdir for each PCR banks
   algorithm configured in the TPM.
   (suggested by Roberto)

Signed-off-by: Enrico Bravi <enrico.bravi@polito.it>
Signed-off-by: Silvia Sisinni <silvia.sisinni@polito.it>

---
 security/integrity/ima/ima_fs.c | 164 ++++++++++++++++++++++++++++++--
 1 file changed, 157 insertions(+), 7 deletions(-)

base-commit: 88035e5694a86a7167d490bb95e9df97a9bb162b

Comments

Roberto Sassu Jan. 22, 2024, 8:20 a.m. UTC | #1
On Sun, 2024-01-21 at 17:16 +0100, Enrico Bravi wrote:
> The template hash showed by the ascii_runtime_measurements and
> binary_runtime_measurements is the one calculated using sha1 and there is no
> possibility to change this value, despite the fact that the template hash is
> calculated using the hash algorothms corresponding to all the PCR banks
> configured in the TPM.
> 
> This patch introduce the support to retrieve the ima log with the template data
> hash calculated with a specific hash algorithm.
> Add a new file in the securityfs ima directory for each hash algo configured
> for the PCR banks of the TPM. Each new file has the name with the following
> structure:
> 
> 	{binary, ascii}_runtime_measurements_<hash_algo_name>
> 
> except for sha1 which it remains associated with the standard file names.
> The <hash_algo_name> is used to select the template data hash algorithm to show
> in ima_ascii_measurements_show() and in ima_measurements_show().
> 
> As example, in the case sha1 and sha256 are the configured PCR banks, the
> listing of the security/ima directory is the following:
> 
> -r--r----- 1 root root 0 gen 20 15:06 ascii_runtime_measurements
> -r--r----- 1 root root 0 gen 20 15:06 ascii_runtime_measurements_sha256
> -r--r----- 1 root root 0 gen 20 15:06 binary_runtime_measurements
> -r--r----- 1 root root 0 gen 20 15:06 binary_runtime_measurements_sha256
> --w------- 1 root root 0 gen 20 15:06 policy
> -r--r----- 1 root root 0 gen 20 15:06 runtime_measurements_count
> -r--r----- 1 root root 0 gen 20 15:06 violations
> 
> v2:
>  - Changed the behaviour of configuring at boot time the template data hash
>    algorithm.
>  - Removed template data hash algo name prefix.
>  - Removed ima_template_hash command line option.
>  - Introducing a new file in the securityfs ima subdir for each PCR banks
>    algorithm configured in the TPM.
>    (suggested by Roberto)
> 
> Signed-off-by: Enrico Bravi <enrico.bravi@polito.it>
> Signed-off-by: Silvia Sisinni <silvia.sisinni@polito.it>
> 
> ---
>  security/integrity/ima/ima_fs.c | 164 ++++++++++++++++++++++++++++++--
>  1 file changed, 157 insertions(+), 7 deletions(-)
> 
> diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
> index cd1683dad3bf..db57edeb112d 100644
> --- a/security/integrity/ima/ima_fs.c
> +++ b/security/integrity/ima/ima_fs.c
> @@ -118,7 +118,7 @@ void ima_putc(struct seq_file *m, void *data, int datalen)
>  
>  /* print format:
>   *       32bit-le=pcr#
> - *       char[20]=template digest
> + *       char[n]=template digest
>   *       32bit-le=template name size
>   *       char[n]=template name
>   *       [eventdata length]
> @@ -130,9 +130,37 @@ int ima_measurements_show(struct seq_file *m, void *v)
>  	struct ima_queue_entry *qe = v;
>  	struct ima_template_entry *e;
>  	char *template_name;
> +	const char *filename;
> +	char algo_name[16];
>  	u32 pcr, namelen, template_data_len; /* temporary fields */
>  	bool is_ima_template = false;
> -	int i;
> +	int i, rc, algo_idx;
> +	enum hash_algo algo;
> +
> +	filename = m->file->f_path.dentry->d_name.name;
> +	rc = sscanf(filename, "binary_runtime_measurements%s", algo_name);
> +
> +	if (rc != 0) {
> +		for (i = 0; i < HASH_ALGO__LAST; i++) {
> +			if (!strcmp(algo_name + 1, hash_algo_name[i])) {
> +				algo = i;
> +				break;
> +			}
> +		}
> +		if (i == HASH_ALGO__LAST)
> +			algo = HASH_ALGO_SHA1;
> +
> +		for (i = 0; i < NR_BANKS(ima_tpm_chip); i++) {
> +			if (algo == ima_tpm_chip->allocated_banks[i].crypto_id) {
> +				algo_idx = i;
> +				break;
> +			}
> +		}
> +	}

Hi Enrico, Silvia

I would find more efficient if you create an array of dentries in the
same order as ima_tpm_chip->allocated_banks, so that you can compare
dentry addresses and find already the right index.

> +	else {
> +		algo_idx = ima_sha1_idx;
> +		algo = HASH_ALGO_SHA1;
> +	}
>  
>  	/* get entry */
>  	e = qe->entry;
> @@ -151,7 +179,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 +248,35 @@ 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;
> +	const char *filename;
> +	char algo_name[16];
> +	int i, algo_idx, rc;
> +	enum hash_algo algo;
> +
> +	filename = m->file->f_path.dentry->d_name.name;
> +	rc = sscanf(filename, "ascii_runtime_measurements%s", algo_name);
> +
> +	if (rc != 0) {
> +		for (i = 0; i < HASH_ALGO__LAST; i++) {
> +			if (!strcmp(algo_name + 1, hash_algo_name[i])) {
> +				algo = i;
> +				break;
> +			}
> +		}
> +		if (i == HASH_ALGO__LAST)
> +			algo = HASH_ALGO_SHA1;
> +
> +		for (i = 0; i < NR_BANKS(ima_tpm_chip); i++) {
> +			if (algo == ima_tpm_chip->allocated_banks[i].crypto_id) {
> +				algo_idx = i;
> +				break;
> +			}
> +		}
> +	}

Same.

> +	else {
> +		algo_idx = ima_sha1_idx;
> +		algo = HASH_ALGO_SHA1;
> +	}
>  
>  	/* get entry */
>  	e = qe->entry;
> @@ -233,8 +289,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);
> @@ -363,6 +419,8 @@ static struct dentry *ascii_runtime_measurements;
>  static struct dentry *runtime_measurements_count;
>  static struct dentry *violations;
>  static struct dentry *ima_policy;
> +static struct dentry **ima_ascii_measurements_files;
> +static struct dentry **ima_binary_measurements_files;
>  
>  enum ima_fs_flags {
>  	IMA_FS_BUSY,
> @@ -379,6 +437,31 @@ static const struct seq_operations ima_policy_seqops = {
>  };
>  #endif
>  
> +/*
> + * Remove the securityfs files created for each hash algo configured
> + * in the TPM, excluded ascii_runtime_measurements and
> + * binary_runtime_measurements.
> + */
> +static void remove_measurements_list_files(void)
> +{
> +	int i;
> +
> +	for (i = 0; i < NR_BANKS(ima_tpm_chip); i++) {
> +		if (ima_ascii_measurements_files[i]) {
> +			securityfs_remove(ima_ascii_measurements_files[i]);
> +			kfree(ima_ascii_measurements_files[i]);
> +		}
> +
> +		if (ima_binary_measurements_files[i]) {
> +			securityfs_remove(ima_binary_measurements_files[i]);
> +			kfree(ima_binary_measurements_files[i]);
> +		}
> +	}
> +
> +	kfree(ima_ascii_measurements_files);
> +	kfree(ima_binary_measurements_files);

Oh, you actually put them in a array and order the elements by PCR
bank.

> +}
> +
>  /*
>   * ima_open_policy: sequentialize access to the policy file
>   */
> @@ -452,7 +535,10 @@ static const struct file_operations ima_measure_policy_ops = {
>  
>  int __init ima_fs_init(void)
>  {
> -	int ret;
> +	int ret, i;
> +	u16 algo;
> +	char file_name[50];
> +	struct dentry *dfile;
>  
>  	ima_dir = securityfs_create_dir("ima", integrity_dir);
>  	if (IS_ERR(ima_dir))
> @@ -483,6 +569,69 @@ int __init ima_fs_init(void)
>  		goto out;
>  	}
>  
> +	/*
> +	 * Allocate a file in the securityfs for each hash algo configured
> +	 * in the TPM but sha1 (for ascii and binary output).
> +	 */
> +	if (ima_tpm_chip) {
> +
> +		ima_ascii_measurements_files = kmalloc_array(NR_BANKS(ima_tpm_chip),
> +					sizeof(struct dentry *), GFP_KERNEL);

Since you added a function for freeing the arrays, I would do the same
for adding.

> +		if(ima_ascii_measurements_files == NULL) {
> +			ret = -ENOMEM;
> +			goto out;
> +		}
> +
> +		ima_binary_measurements_files = kmalloc_array(NR_BANKS(ima_tpm_chip),
> +					sizeof(struct dentry *), GFP_KERNEL);
> +		if(ima_binary_measurements_files == NULL) {
> +			ret = -ENOMEM;
> +			goto out;
> +		}
> +
> +		for (i = 0; i < NR_BANKS(ima_tpm_chip); i++) {
> +			algo = ima_tpm_chip->allocated_banks[i].crypto_id;
> +
> +			/* Skip sha1 */
> +			if (algo == HASH_ALGO_SHA1)
> +				continue;

I would go ahead, create also the dentry for SHA1 and add a symbolic
link for the legacy files.

> +
> +			dfile = kmalloc(sizeof(struct dentry), GFP_KERNEL);
> +			if (!dfile) {
> +				ret = -ENOMEM;
> +				goto out;
> +			}

I don't remember if the lines above are really necessary. You actually
overwrite the pointer below.

Thanks

Roberto

> +
> +			sprintf(file_name, "ascii_runtime_measurements_%s",
> +						hash_algo_name[algo]);
> +			dfile = securityfs_create_file(file_name,
> +						S_IRUSR | S_IRGRP, ima_dir, NULL,
> +						&ima_ascii_measurements_ops);
> +			if (IS_ERR(dfile)) {
> +				ret = PTR_ERR(dfile);
> +				goto out;
> +			}
> +			ima_ascii_measurements_files[i] = dfile;
> +
> +			dfile = kmalloc(sizeof(struct dentry), GFP_KERNEL);
> +			if (!dfile) {
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +
> +			sprintf(file_name, "binary_runtime_measurements_%s",
> +						hash_algo_name[algo]);
> +			dfile = securityfs_create_file(file_name,
> +						S_IRUSR | S_IRGRP, ima_dir, NULL,
> +						&ima_measurements_ops);
> +			if (IS_ERR(dfile)) {
> +				ret = PTR_ERR(dfile);
> +				goto out;
> +			}
> +			ima_binary_measurements_files[i] = dfile;
> +		}
> +	}
> +
>  	runtime_measurements_count =
>  	    securityfs_create_file("runtime_measurements_count",
>  				   S_IRUSR | S_IRGRP, ima_dir, NULL,
> @@ -515,6 +664,7 @@ int __init ima_fs_init(void)
>  	securityfs_remove(runtime_measurements_count);
>  	securityfs_remove(ascii_runtime_measurements);
>  	securityfs_remove(binary_runtime_measurements);
> +	remove_measurements_list_files();
>  	securityfs_remove(ima_symlink);
>  	securityfs_remove(ima_dir);
> 
> base-commit: 88035e5694a86a7167d490bb95e9df97a9bb162b
Enrico Bravi Jan. 22, 2024, 5:41 p.m. UTC | #2
Hi Roberto,

thanks a lot for your quick feedback.

On 22/01/24 09:20, Roberto Sassu wrote:
> On Sun, 2024-01-21 at 17:16 +0100, Enrico Bravi wrote:
>> The template hash showed by the ascii_runtime_measurements and
>> binary_runtime_measurements is the one calculated using sha1 and there is no
>> possibility to change this value, despite the fact that the template hash is
>> calculated using the hash algorothms corresponding to all the PCR banks
>> configured in the TPM.
>>
>> This patch introduce the support to retrieve the ima log with the template data
>> hash calculated with a specific hash algorithm.
>> Add a new file in the securityfs ima directory for each hash algo configured
>> for the PCR banks of the TPM. Each new file has the name with the following
>> structure:
>>
>> 	{binary, ascii}_runtime_measurements_<hash_algo_name>
>>
>> except for sha1 which it remains associated with the standard file names.
>> The <hash_algo_name> is used to select the template data hash algorithm to show
>> in ima_ascii_measurements_show() and in ima_measurements_show().
>>
>> As example, in the case sha1 and sha256 are the configured PCR banks, the
>> listing of the security/ima directory is the following:
>>
>> -r--r----- 1 root root 0 gen 20 15:06 ascii_runtime_measurements
>> -r--r----- 1 root root 0 gen 20 15:06 ascii_runtime_measurements_sha256
>> -r--r----- 1 root root 0 gen 20 15:06 binary_runtime_measurements
>> -r--r----- 1 root root 0 gen 20 15:06 binary_runtime_measurements_sha256
>> --w------- 1 root root 0 gen 20 15:06 policy
>> -r--r----- 1 root root 0 gen 20 15:06 runtime_measurements_count
>> -r--r----- 1 root root 0 gen 20 15:06 violations
>>
>> v2:
>>  - Changed the behaviour of configuring at boot time the template data hash
>>    algorithm.
>>  - Removed template data hash algo name prefix.
>>  - Removed ima_template_hash command line option.
>>  - Introducing a new file in the securityfs ima subdir for each PCR banks
>>    algorithm configured in the TPM.
>>    (suggested by Roberto)
>>
>> Signed-off-by: Enrico Bravi <enrico.bravi@polito.it>
>> Signed-off-by: Silvia Sisinni <silvia.sisinni@polito.it>
>>
>> ---
>>  security/integrity/ima/ima_fs.c | 164 ++++++++++++++++++++++++++++++--
>>  1 file changed, 157 insertions(+), 7 deletions(-)
>>
>> diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
>> index cd1683dad3bf..db57edeb112d 100644
>> --- a/security/integrity/ima/ima_fs.c
>> +++ b/security/integrity/ima/ima_fs.c
>> @@ -118,7 +118,7 @@ void ima_putc(struct seq_file *m, void *data, int datalen)
>>  
>>  /* print format:
>>   *       32bit-le=pcr#
>> - *       char[20]=template digest
>> + *       char[n]=template digest
>>   *       32bit-le=template name size
>>   *       char[n]=template name
>>   *       [eventdata length]
>> @@ -130,9 +130,37 @@ int ima_measurements_show(struct seq_file *m, void *v)
>>  	struct ima_queue_entry *qe = v;
>>  	struct ima_template_entry *e;
>>  	char *template_name;
>> +	const char *filename;
>> +	char algo_name[16];
>>  	u32 pcr, namelen, template_data_len; /* temporary fields */
>>  	bool is_ima_template = false;
>> -	int i;
>> +	int i, rc, algo_idx;
>> +	enum hash_algo algo;
>> +
>> +	filename = m->file->f_path.dentry->d_name.name;
>> +	rc = sscanf(filename, "binary_runtime_measurements%s", algo_name);
>> +
>> +	if (rc != 0) {
>> +		for (i = 0; i < HASH_ALGO__LAST; i++) {
>> +			if (!strcmp(algo_name + 1, hash_algo_name[i])) {
>> +				algo = i;
>> +				break;
>> +			}
>> +		}
>> +		if (i == HASH_ALGO__LAST)
>> +			algo = HASH_ALGO_SHA1;
>> +
>> +		for (i = 0; i < NR_BANKS(ima_tpm_chip); i++) {
>> +			if (algo == ima_tpm_chip->allocated_banks[i].crypto_id) {
>> +				algo_idx = i;
>> +				break;
>> +			}
>> +		}
>> +	}
> 
> Hi Enrico, Silvia
> 
> I would find more efficient if you create an array of dentries in the
> same order as ima_tpm_chip->allocated_banks, so that you can compare
> dentry addresses and find already the right index.

Your are absolutely right, there is no need of two loops.

>> +	else {
>> +		algo_idx = ima_sha1_idx;
>> +		algo = HASH_ALGO_SHA1;
>> +	}
>>  
>>  	/* get entry */
>>  	e = qe->entry;
>> @@ -151,7 +179,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 +248,35 @@ 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;
>> +	const char *filename;
>> +	char algo_name[16];
>> +	int i, algo_idx, rc;
>> +	enum hash_algo algo;
>> +
>> +	filename = m->file->f_path.dentry->d_name.name;
>> +	rc = sscanf(filename, "ascii_runtime_measurements%s", algo_name);
>> +
>> +	if (rc != 0) {
>> +		for (i = 0; i < HASH_ALGO__LAST; i++) {
>> +			if (!strcmp(algo_name + 1, hash_algo_name[i])) {
>> +				algo = i;
>> +				break;
>> +			}
>> +		}
>> +		if (i == HASH_ALGO__LAST)
>> +			algo = HASH_ALGO_SHA1;
>> +
>> +		for (i = 0; i < NR_BANKS(ima_tpm_chip); i++) {
>> +			if (algo == ima_tpm_chip->allocated_banks[i].crypto_id) {
>> +				algo_idx = i;
>> +				break;
>> +			}
>> +		}
>> +	}
> 
> Same.
> 
>> +	else {
>> +		algo_idx = ima_sha1_idx;
>> +		algo = HASH_ALGO_SHA1;
>> +	}
>>  
>>  	/* get entry */
>>  	e = qe->entry;
>> @@ -233,8 +289,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);
>> @@ -363,6 +419,8 @@ static struct dentry *ascii_runtime_measurements;
>>  static struct dentry *runtime_measurements_count;
>>  static struct dentry *violations;
>>  static struct dentry *ima_policy;
>> +static struct dentry **ima_ascii_measurements_files;
>> +static struct dentry **ima_binary_measurements_files;
>>  
>>  enum ima_fs_flags {
>>  	IMA_FS_BUSY,
>> @@ -379,6 +437,31 @@ static const struct seq_operations ima_policy_seqops = {
>>  };
>>  #endif
>>  
>> +/*
>> + * Remove the securityfs files created for each hash algo configured
>> + * in the TPM, excluded ascii_runtime_measurements and
>> + * binary_runtime_measurements.
>> + */
>> +static void remove_measurements_list_files(void)
>> +{
>> +	int i;
>> +
>> +	for (i = 0; i < NR_BANKS(ima_tpm_chip); i++) {
>> +		if (ima_ascii_measurements_files[i]) {
>> +			securityfs_remove(ima_ascii_measurements_files[i]);
>> +			kfree(ima_ascii_measurements_files[i]);
>> +		}
>> +
>> +		if (ima_binary_measurements_files[i]) {
>> +			securityfs_remove(ima_binary_measurements_files[i]);
>> +			kfree(ima_binary_measurements_files[i]);
>> +		}
>> +	}
>> +
>> +	kfree(ima_ascii_measurements_files);
>> +	kfree(ima_binary_measurements_files);
> 
> Oh, you actually put them in a array and order the elements by PCR
> bank.
> 
>> +}
>> +
>>  /*
>>   * ima_open_policy: sequentialize access to the policy file
>>   */
>> @@ -452,7 +535,10 @@ static const struct file_operations ima_measure_policy_ops = {
>>  
>>  int __init ima_fs_init(void)
>>  {
>> -	int ret;
>> +	int ret, i;
>> +	u16 algo;
>> +	char file_name[50];
>> +	struct dentry *dfile;
>>  
>>  	ima_dir = securityfs_create_dir("ima", integrity_dir);
>>  	if (IS_ERR(ima_dir))
>> @@ -483,6 +569,69 @@ int __init ima_fs_init(void)
>>  		goto out;
>>  	}
>>  
>> +	/*
>> +	 * Allocate a file in the securityfs for each hash algo configured
>> +	 * in the TPM but sha1 (for ascii and binary output).
>> +	 */
>> +	if (ima_tpm_chip) {
>> +
>> +		ima_ascii_measurements_files = kmalloc_array(NR_BANKS(ima_tpm_chip),
>> +					sizeof(struct dentry *), GFP_KERNEL);
> 
> Since you added a function for freeing the arrays, I would do the same
> for adding.

Sure.

>> +		if(ima_ascii_measurements_files == NULL) {
>> +			ret = -ENOMEM;
>> +			goto out;
>> +		}
>> +
>> +		ima_binary_measurements_files = kmalloc_array(NR_BANKS(ima_tpm_chip),
>> +					sizeof(struct dentry *), GFP_KERNEL);
>> +		if(ima_binary_measurements_files == NULL) {
>> +			ret = -ENOMEM;
>> +			goto out;
>> +		}
>> +
>> +		for (i = 0; i < NR_BANKS(ima_tpm_chip); i++) {
>> +			algo = ima_tpm_chip->allocated_banks[i].crypto_id;
>> +
>> +			/* Skip sha1 */
>> +			if (algo == HASH_ALGO_SHA1)
>> +				continue;
> 
> I would go ahead, create also the dentry for SHA1 and add a symbolic
> link for the legacy files.

ima_ascii_measurements_files and ima_binary_measurements_files are allocated
just in the case a tpm chip is detected. What you are suggesting is to allocate
in any case these lists, with at least one element, and creating the legacy file
always as symbolic links? Or to define them as symbolic links only in the case a
tpm chip is detected, otherwise creating them as usual?

>> +
>> +			dfile = kmalloc(sizeof(struct dentry), GFP_KERNEL);
>> +			if (!dfile) {
>> +				ret = -ENOMEM;
>> +				goto out;
>> +			}
> 
> I don't remember if the lines above are really necessary. You actually
> overwrite the pointer below.

Yes these lines are definitely not necessary.

Thanks a lot,

Enrico

> 
>> +
>> +			sprintf(file_name, "ascii_runtime_measurements_%s",
>> +						hash_algo_name[algo]);
>> +			dfile = securityfs_create_file(file_name,
>> +						S_IRUSR | S_IRGRP, ima_dir, NULL,
>> +						&ima_ascii_measurements_ops);
>> +			if (IS_ERR(dfile)) {
>> +				ret = PTR_ERR(dfile);
>> +				goto out;
>> +			}
>> +			ima_ascii_measurements_files[i] = dfile;
>> +
>> +			dfile = kmalloc(sizeof(struct dentry), GFP_KERNEL);
>> +			if (!dfile) {
>> +				ret = -ENOMEM;
>> +				goto out;
>> +			}
>> +
>> +			sprintf(file_name, "binary_runtime_measurements_%s",
>> +						hash_algo_name[algo]);
>> +			dfile = securityfs_create_file(file_name,
>> +						S_IRUSR | S_IRGRP, ima_dir, NULL,
>> +						&ima_measurements_ops);
>> +			if (IS_ERR(dfile)) {
>> +				ret = PTR_ERR(dfile);
>> +				goto out;
>> +			}
>> +			ima_binary_measurements_files[i] = dfile;
>> +		}
>> +	}
>> +
>>  	runtime_measurements_count =
>>  	    securityfs_create_file("runtime_measurements_count",
>>  				   S_IRUSR | S_IRGRP, ima_dir, NULL,
>> @@ -515,6 +664,7 @@ int __init ima_fs_init(void)
>>  	securityfs_remove(runtime_measurements_count);
>>  	securityfs_remove(ascii_runtime_measurements);
>>  	securityfs_remove(binary_runtime_measurements);
>> +	remove_measurements_list_files();
>>  	securityfs_remove(ima_symlink);
>>  	securityfs_remove(ima_dir);
>>
>> base-commit: 88035e5694a86a7167d490bb95e9df97a9bb162b
Roberto Sassu Jan. 23, 2024, 8:03 a.m. UTC | #3
On Mon, 2024-01-22 at 18:41 +0100, Enrico Bravi wrote:
> Hi Roberto,
> 
> thanks a lot for your quick feedback.
> 
> On 22/01/24 09:20, Roberto Sassu wrote:
> > On Sun, 2024-01-21 at 17:16 +0100, Enrico Bravi wrote:
> > > The template hash showed by the ascii_runtime_measurements and
> > > binary_runtime_measurements is the one calculated using sha1 and there is no
> > > possibility to change this value, despite the fact that the template hash is
> > > calculated using the hash algorothms corresponding to all the PCR banks
> > > configured in the TPM.
> > > 
> > > This patch introduce the support to retrieve the ima log with the template data
> > > hash calculated with a specific hash algorithm.
> > > Add a new file in the securityfs ima directory for each hash algo configured
> > > for the PCR banks of the TPM. Each new file has the name with the following
> > > structure:
> > > 
> > > 	{binary, ascii}_runtime_measurements_<hash_algo_name>
> > > 
> > > except for sha1 which it remains associated with the standard file names.
> > > The <hash_algo_name> is used to select the template data hash algorithm to show
> > > in ima_ascii_measurements_show() and in ima_measurements_show().
> > > 
> > > As example, in the case sha1 and sha256 are the configured PCR banks, the
> > > listing of the security/ima directory is the following:
> > > 
> > > -r--r----- 1 root root 0 gen 20 15:06 ascii_runtime_measurements
> > > -r--r----- 1 root root 0 gen 20 15:06 ascii_runtime_measurements_sha256
> > > -r--r----- 1 root root 0 gen 20 15:06 binary_runtime_measurements
> > > -r--r----- 1 root root 0 gen 20 15:06 binary_runtime_measurements_sha256
> > > --w------- 1 root root 0 gen 20 15:06 policy
> > > -r--r----- 1 root root 0 gen 20 15:06 runtime_measurements_count
> > > -r--r----- 1 root root 0 gen 20 15:06 violations
> > > 
> > > v2:
> > >  - Changed the behaviour of configuring at boot time the template data hash
> > >    algorithm.
> > >  - Removed template data hash algo name prefix.
> > >  - Removed ima_template_hash command line option.
> > >  - Introducing a new file in the securityfs ima subdir for each PCR banks
> > >    algorithm configured in the TPM.
> > >    (suggested by Roberto)
> > > 
> > > Signed-off-by: Enrico Bravi <enrico.bravi@polito.it>
> > > Signed-off-by: Silvia Sisinni <silvia.sisinni@polito.it>
> > > 
> > > ---
> > >  security/integrity/ima/ima_fs.c | 164 ++++++++++++++++++++++++++++++--
> > >  1 file changed, 157 insertions(+), 7 deletions(-)
> > > 
> > > diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
> > > index cd1683dad3bf..db57edeb112d 100644
> > > --- a/security/integrity/ima/ima_fs.c
> > > +++ b/security/integrity/ima/ima_fs.c
> > > @@ -118,7 +118,7 @@ void ima_putc(struct seq_file *m, void *data, int datalen)
> > >  
> > >  /* print format:
> > >   *       32bit-le=pcr#
> > > - *       char[20]=template digest
> > > + *       char[n]=template digest
> > >   *       32bit-le=template name size
> > >   *       char[n]=template name
> > >   *       [eventdata length]
> > > @@ -130,9 +130,37 @@ int ima_measurements_show(struct seq_file *m, void *v)
> > >  	struct ima_queue_entry *qe = v;
> > >  	struct ima_template_entry *e;
> > >  	char *template_name;
> > > +	const char *filename;
> > > +	char algo_name[16];
> > >  	u32 pcr, namelen, template_data_len; /* temporary fields */
> > >  	bool is_ima_template = false;
> > > -	int i;
> > > +	int i, rc, algo_idx;
> > > +	enum hash_algo algo;
> > > +
> > > +	filename = m->file->f_path.dentry->d_name.name;
> > > +	rc = sscanf(filename, "binary_runtime_measurements%s", algo_name);
> > > +
> > > +	if (rc != 0) {
> > > +		for (i = 0; i < HASH_ALGO__LAST; i++) {
> > > +			if (!strcmp(algo_name + 1, hash_algo_name[i])) {
> > > +				algo = i;
> > > +				break;
> > > +			}
> > > +		}
> > > +		if (i == HASH_ALGO__LAST)
> > > +			algo = HASH_ALGO_SHA1;
> > > +
> > > +		for (i = 0; i < NR_BANKS(ima_tpm_chip); i++) {
> > > +			if (algo == ima_tpm_chip->allocated_banks[i].crypto_id) {
> > > +				algo_idx = i;
> > > +				break;
> > > +			}
> > > +		}
> > > +	}
> > 
> > Hi Enrico, Silvia
> > 
> > I would find more efficient if you create an array of dentries in the
> > same order as ima_tpm_chip->allocated_banks, so that you can compare
> > dentry addresses and find already the right index.
> 
> Your are absolutely right, there is no need of two loops.
> 
> > > +	else {
> > > +		algo_idx = ima_sha1_idx;
> > > +		algo = HASH_ALGO_SHA1;
> > > +	}
> > >  
> > >  	/* get entry */
> > >  	e = qe->entry;
> > > @@ -151,7 +179,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 +248,35 @@ 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;
> > > +	const char *filename;
> > > +	char algo_name[16];
> > > +	int i, algo_idx, rc;
> > > +	enum hash_algo algo;
> > > +
> > > +	filename = m->file->f_path.dentry->d_name.name;
> > > +	rc = sscanf(filename, "ascii_runtime_measurements%s", algo_name);
> > > +
> > > +	if (rc != 0) {
> > > +		for (i = 0; i < HASH_ALGO__LAST; i++) {
> > > +			if (!strcmp(algo_name + 1, hash_algo_name[i])) {
> > > +				algo = i;
> > > +				break;
> > > +			}
> > > +		}
> > > +		if (i == HASH_ALGO__LAST)
> > > +			algo = HASH_ALGO_SHA1;
> > > +
> > > +		for (i = 0; i < NR_BANKS(ima_tpm_chip); i++) {
> > > +			if (algo == ima_tpm_chip->allocated_banks[i].crypto_id) {
> > > +				algo_idx = i;
> > > +				break;
> > > +			}
> > > +		}
> > > +	}
> > 
> > Same.
> > 
> > > +	else {
> > > +		algo_idx = ima_sha1_idx;
> > > +		algo = HASH_ALGO_SHA1;
> > > +	}
> > >  
> > >  	/* get entry */
> > >  	e = qe->entry;
> > > @@ -233,8 +289,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);
> > > @@ -363,6 +419,8 @@ static struct dentry *ascii_runtime_measurements;
> > >  static struct dentry *runtime_measurements_count;
> > >  static struct dentry *violations;
> > >  static struct dentry *ima_policy;
> > > +static struct dentry **ima_ascii_measurements_files;
> > > +static struct dentry **ima_binary_measurements_files;
> > >  
> > >  enum ima_fs_flags {
> > >  	IMA_FS_BUSY,
> > > @@ -379,6 +437,31 @@ static const struct seq_operations ima_policy_seqops = {
> > >  };
> > >  #endif
> > >  
> > > +/*
> > > + * Remove the securityfs files created for each hash algo configured
> > > + * in the TPM, excluded ascii_runtime_measurements and
> > > + * binary_runtime_measurements.
> > > + */
> > > +static void remove_measurements_list_files(void)
> > > +{
> > > +	int i;
> > > +
> > > +	for (i = 0; i < NR_BANKS(ima_tpm_chip); i++) {
> > > +		if (ima_ascii_measurements_files[i]) {
> > > +			securityfs_remove(ima_ascii_measurements_files[i]);
> > > +			kfree(ima_ascii_measurements_files[i]);
> > > +		}
> > > +
> > > +		if (ima_binary_measurements_files[i]) {
> > > +			securityfs_remove(ima_binary_measurements_files[i]);
> > > +			kfree(ima_binary_measurements_files[i]);
> > > +		}
> > > +	}
> > > +
> > > +	kfree(ima_ascii_measurements_files);
> > > +	kfree(ima_binary_measurements_files);
> > 
> > Oh, you actually put them in a array and order the elements by PCR
> > bank.
> > 
> > > +}
> > > +
> > >  /*
> > >   * ima_open_policy: sequentialize access to the policy file
> > >   */
> > > @@ -452,7 +535,10 @@ static const struct file_operations ima_measure_policy_ops = {
> > >  
> > >  int __init ima_fs_init(void)
> > >  {
> > > -	int ret;
> > > +	int ret, i;
> > > +	u16 algo;
> > > +	char file_name[50];
> > > +	struct dentry *dfile;
> > >  
> > >  	ima_dir = securityfs_create_dir("ima", integrity_dir);
> > >  	if (IS_ERR(ima_dir))
> > > @@ -483,6 +569,69 @@ int __init ima_fs_init(void)
> > >  		goto out;
> > >  	}
> > >  
> > > +	/*
> > > +	 * Allocate a file in the securityfs for each hash algo configured
> > > +	 * in the TPM but sha1 (for ascii and binary output).
> > > +	 */
> > > +	if (ima_tpm_chip) {
> > > +
> > > +		ima_ascii_measurements_files = kmalloc_array(NR_BANKS(ima_tpm_chip),
> > > +					sizeof(struct dentry *), GFP_KERNEL);
> > 
> > Since you added a function for freeing the arrays, I would do the same
> > for adding.
> 
> Sure.
> 
> > > +		if(ima_ascii_measurements_files == NULL) {
> > > +			ret = -ENOMEM;
> > > +			goto out;
> > > +		}
> > > +
> > > +		ima_binary_measurements_files = kmalloc_array(NR_BANKS(ima_tpm_chip),
> > > +					sizeof(struct dentry *), GFP_KERNEL);
> > > +		if(ima_binary_measurements_files == NULL) {
> > > +			ret = -ENOMEM;
> > > +			goto out;
> > > +		}
> > > +
> > > +		for (i = 0; i < NR_BANKS(ima_tpm_chip); i++) {
> > > +			algo = ima_tpm_chip->allocated_banks[i].crypto_id;
> > > +
> > > +			/* Skip sha1 */
> > > +			if (algo == HASH_ALGO_SHA1)
> > > +				continue;
> > 
> > I would go ahead, create also the dentry for SHA1 and add a symbolic
> > link for the legacy files.
> 
> ima_ascii_measurements_files and ima_binary_measurements_files are allocated
> just in the case a tpm chip is detected. What you are suggesting is to allocate
> in any case these lists, with at least one element, and creating the legacy file
> always as symbolic links? Or to define them as symbolic links only in the case a
> tpm chip is detected, otherwise creating them as usual?

Hi Enrico

I would keep the same scheme, even if there is no TPM chip. So SHA1
files, plus symbolic links in this case.

Thanks

Roberto

> > > +
> > > +			dfile = kmalloc(sizeof(struct dentry), GFP_KERNEL);
> > > +			if (!dfile) {
> > > +				ret = -ENOMEM;
> > > +				goto out;
> > > +			}
> > 
> > I don't remember if the lines above are really necessary. You actually
> > overwrite the pointer below.
> 
> Yes these lines are definitely not necessary.
> 
> Thanks a lot,
> 
> Enrico
> 
> > 
> > > +
> > > +			sprintf(file_name, "ascii_runtime_measurements_%s",
> > > +						hash_algo_name[algo]);
> > > +			dfile = securityfs_create_file(file_name,
> > > +						S_IRUSR | S_IRGRP, ima_dir, NULL,
> > > +						&ima_ascii_measurements_ops);
> > > +			if (IS_ERR(dfile)) {
> > > +				ret = PTR_ERR(dfile);
> > > +				goto out;
> > > +			}
> > > +			ima_ascii_measurements_files[i] = dfile;
> > > +
> > > +			dfile = kmalloc(sizeof(struct dentry), GFP_KERNEL);
> > > +			if (!dfile) {
> > > +				ret = -ENOMEM;
> > > +				goto out;
> > > +			}
> > > +
> > > +			sprintf(file_name, "binary_runtime_measurements_%s",
> > > +						hash_algo_name[algo]);
> > > +			dfile = securityfs_create_file(file_name,
> > > +						S_IRUSR | S_IRGRP, ima_dir, NULL,
> > > +						&ima_measurements_ops);
> > > +			if (IS_ERR(dfile)) {
> > > +				ret = PTR_ERR(dfile);
> > > +				goto out;
> > > +			}
> > > +			ima_binary_measurements_files[i] = dfile;
> > > +		}
> > > +	}
> > > +
> > >  	runtime_measurements_count =
> > >  	    securityfs_create_file("runtime_measurements_count",
> > >  				   S_IRUSR | S_IRGRP, ima_dir, NULL,
> > > @@ -515,6 +664,7 @@ int __init ima_fs_init(void)
> > >  	securityfs_remove(runtime_measurements_count);
> > >  	securityfs_remove(ascii_runtime_measurements);
> > >  	securityfs_remove(binary_runtime_measurements);
> > > +	remove_measurements_list_files();
> > >  	securityfs_remove(ima_symlink);
> > >  	securityfs_remove(ima_dir);
> > > 
> > > base-commit: 88035e5694a86a7167d490bb95e9df97a9bb162b
diff mbox series

Patch

diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index cd1683dad3bf..db57edeb112d 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -118,7 +118,7 @@  void ima_putc(struct seq_file *m, void *data, int datalen)
 
 /* print format:
  *       32bit-le=pcr#
- *       char[20]=template digest
+ *       char[n]=template digest
  *       32bit-le=template name size
  *       char[n]=template name
  *       [eventdata length]
@@ -130,9 +130,37 @@  int ima_measurements_show(struct seq_file *m, void *v)
 	struct ima_queue_entry *qe = v;
 	struct ima_template_entry *e;
 	char *template_name;
+	const char *filename;
+	char algo_name[16];
 	u32 pcr, namelen, template_data_len; /* temporary fields */
 	bool is_ima_template = false;
-	int i;
+	int i, rc, algo_idx;
+	enum hash_algo algo;
+
+	filename = m->file->f_path.dentry->d_name.name;
+	rc = sscanf(filename, "binary_runtime_measurements%s", algo_name);
+
+	if (rc != 0) {
+		for (i = 0; i < HASH_ALGO__LAST; i++) {
+			if (!strcmp(algo_name + 1, hash_algo_name[i])) {
+				algo = i;
+				break;
+			}
+		}
+		if (i == HASH_ALGO__LAST)
+			algo = HASH_ALGO_SHA1;
+
+		for (i = 0; i < NR_BANKS(ima_tpm_chip); i++) {
+			if (algo == ima_tpm_chip->allocated_banks[i].crypto_id) {
+				algo_idx = i;
+				break;
+			}
+		}
+	}
+	else {
+		algo_idx = ima_sha1_idx;
+		algo = HASH_ALGO_SHA1;
+	}
 
 	/* get entry */
 	e = qe->entry;
@@ -151,7 +179,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 +248,35 @@  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;
+	const char *filename;
+	char algo_name[16];
+	int i, algo_idx, rc;
+	enum hash_algo algo;
+
+	filename = m->file->f_path.dentry->d_name.name;
+	rc = sscanf(filename, "ascii_runtime_measurements%s", algo_name);
+
+	if (rc != 0) {
+		for (i = 0; i < HASH_ALGO__LAST; i++) {
+			if (!strcmp(algo_name + 1, hash_algo_name[i])) {
+				algo = i;
+				break;
+			}
+		}
+		if (i == HASH_ALGO__LAST)
+			algo = HASH_ALGO_SHA1;
+
+		for (i = 0; i < NR_BANKS(ima_tpm_chip); i++) {
+			if (algo == ima_tpm_chip->allocated_banks[i].crypto_id) {
+				algo_idx = i;
+				break;
+			}
+		}
+	}
+	else {
+		algo_idx = ima_sha1_idx;
+		algo = HASH_ALGO_SHA1;
+	}
 
 	/* get entry */
 	e = qe->entry;
@@ -233,8 +289,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);
@@ -363,6 +419,8 @@  static struct dentry *ascii_runtime_measurements;
 static struct dentry *runtime_measurements_count;
 static struct dentry *violations;
 static struct dentry *ima_policy;
+static struct dentry **ima_ascii_measurements_files;
+static struct dentry **ima_binary_measurements_files;
 
 enum ima_fs_flags {
 	IMA_FS_BUSY,
@@ -379,6 +437,31 @@  static const struct seq_operations ima_policy_seqops = {
 };
 #endif
 
+/*
+ * Remove the securityfs files created for each hash algo configured
+ * in the TPM, excluded ascii_runtime_measurements and
+ * binary_runtime_measurements.
+ */
+static void remove_measurements_list_files(void)
+{
+	int i;
+
+	for (i = 0; i < NR_BANKS(ima_tpm_chip); i++) {
+		if (ima_ascii_measurements_files[i]) {
+			securityfs_remove(ima_ascii_measurements_files[i]);
+			kfree(ima_ascii_measurements_files[i]);
+		}
+
+		if (ima_binary_measurements_files[i]) {
+			securityfs_remove(ima_binary_measurements_files[i]);
+			kfree(ima_binary_measurements_files[i]);
+		}
+	}
+
+	kfree(ima_ascii_measurements_files);
+	kfree(ima_binary_measurements_files);
+}
+
 /*
  * ima_open_policy: sequentialize access to the policy file
  */
@@ -452,7 +535,10 @@  static const struct file_operations ima_measure_policy_ops = {
 
 int __init ima_fs_init(void)
 {
-	int ret;
+	int ret, i;
+	u16 algo;
+	char file_name[50];
+	struct dentry *dfile;
 
 	ima_dir = securityfs_create_dir("ima", integrity_dir);
 	if (IS_ERR(ima_dir))
@@ -483,6 +569,69 @@  int __init ima_fs_init(void)
 		goto out;
 	}
 
+	/*
+	 * Allocate a file in the securityfs for each hash algo configured
+	 * in the TPM but sha1 (for ascii and binary output).
+	 */
+	if (ima_tpm_chip) {
+
+		ima_ascii_measurements_files = kmalloc_array(NR_BANKS(ima_tpm_chip),
+					sizeof(struct dentry *), GFP_KERNEL);
+		if(ima_ascii_measurements_files == NULL) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		ima_binary_measurements_files = kmalloc_array(NR_BANKS(ima_tpm_chip),
+					sizeof(struct dentry *), GFP_KERNEL);
+		if(ima_binary_measurements_files == NULL) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		for (i = 0; i < NR_BANKS(ima_tpm_chip); i++) {
+			algo = ima_tpm_chip->allocated_banks[i].crypto_id;
+
+			/* Skip sha1 */
+			if (algo == HASH_ALGO_SHA1)
+				continue;
+
+			dfile = kmalloc(sizeof(struct dentry), GFP_KERNEL);
+			if (!dfile) {
+				ret = -ENOMEM;
+				goto out;
+			}
+
+			sprintf(file_name, "ascii_runtime_measurements_%s",
+						hash_algo_name[algo]);
+			dfile = securityfs_create_file(file_name,
+						S_IRUSR | S_IRGRP, ima_dir, NULL,
+						&ima_ascii_measurements_ops);
+			if (IS_ERR(dfile)) {
+				ret = PTR_ERR(dfile);
+				goto out;
+			}
+			ima_ascii_measurements_files[i] = dfile;
+
+			dfile = kmalloc(sizeof(struct dentry), GFP_KERNEL);
+			if (!dfile) {
+				ret = -ENOMEM;
+				goto out;
+			}
+
+			sprintf(file_name, "binary_runtime_measurements_%s",
+						hash_algo_name[algo]);
+			dfile = securityfs_create_file(file_name,
+						S_IRUSR | S_IRGRP, ima_dir, NULL,
+						&ima_measurements_ops);
+			if (IS_ERR(dfile)) {
+				ret = PTR_ERR(dfile);
+				goto out;
+			}
+			ima_binary_measurements_files[i] = dfile;
+		}
+	}
+
 	runtime_measurements_count =
 	    securityfs_create_file("runtime_measurements_count",
 				   S_IRUSR | S_IRGRP, ima_dir, NULL,
@@ -515,6 +664,7 @@  int __init ima_fs_init(void)
 	securityfs_remove(runtime_measurements_count);
 	securityfs_remove(ascii_runtime_measurements);
 	securityfs_remove(binary_runtime_measurements);
+	remove_measurements_list_files();
 	securityfs_remove(ima_symlink);
 	securityfs_remove(ima_dir);