Skip to content

Commit aa724fe

Browse files
robertosassumimizohar
authored andcommitted
ima: Switch to dynamically allocated buffer for template digests
This patch dynamically allocates the array of tpm_digest structures in ima_alloc_init_template() and ima_restore_template_data(). The size of the array is equal to the number of PCR banks plus ima_extra_slots, to make room for SHA1 and the IMA default hash algorithm, when PCR banks with those algorithms are not allocated. Calculating the SHA1 digest is mandatory, as SHA1 still remains the default hash algorithm for the measurement list. When IMA will support the Crypto Agile format, remaining digests will be also provided. The position in the measurement entry array of the SHA1 digest is stored in the ima_sha1_idx global variable and is determined at IMA initialization time. Signed-off-by: Roberto Sassu <[email protected]> Signed-off-by: Mimi Zohar <[email protected]>
1 parent 7ca7964 commit aa724fe

File tree

6 files changed

+45
-10
lines changed

6 files changed

+45
-10
lines changed

security/integrity/ima/ima.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,15 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
4545
#define IMA_TEMPLATE_IMA_NAME "ima"
4646
#define IMA_TEMPLATE_IMA_FMT "d|n"
4747

48+
#define NR_BANKS(chip) ((chip != NULL) ? chip->nr_allocated_banks : 0)
49+
4850
/* current content of the policy */
4951
extern int ima_policy_flag;
5052

5153
/* set during initialization */
5254
extern int ima_hash_algo;
55+
extern int ima_sha1_idx __ro_after_init;
56+
extern int ima_extra_slots __ro_after_init;
5357
extern int ima_appraise;
5458
extern struct tpm_chip *ima_tpm_chip;
5559

@@ -92,7 +96,7 @@ struct ima_template_desc {
9296

9397
struct ima_template_entry {
9498
int pcr;
95-
u8 digest[TPM_DIGEST_SIZE]; /* sha1 or md5 measurement hash */
99+
struct tpm_digest *digests;
96100
struct ima_template_desc *template_desc; /* template descriptor */
97101
u32 template_data_len;
98102
struct ima_field_data template_data[0]; /* template related data */

security/integrity/ima/ima_api.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ void ima_free_template_entry(struct ima_template_entry *entry)
2727
for (i = 0; i < entry->template_desc->num_fields; i++)
2828
kfree(entry->template_data[i].data);
2929

30+
kfree(entry->digests);
3031
kfree(entry);
3132
}
3233

@@ -38,6 +39,7 @@ int ima_alloc_init_template(struct ima_event_data *event_data,
3839
struct ima_template_desc *desc)
3940
{
4041
struct ima_template_desc *template_desc;
42+
struct tpm_digest *digests;
4143
int i, result = 0;
4244

4345
if (desc)
@@ -50,6 +52,14 @@ int ima_alloc_init_template(struct ima_event_data *event_data,
5052
if (!*entry)
5153
return -ENOMEM;
5254

55+
digests = kcalloc(NR_BANKS(ima_tpm_chip) + ima_extra_slots,
56+
sizeof(*digests), GFP_NOFS);
57+
if (!digests) {
58+
result = -ENOMEM;
59+
goto out;
60+
}
61+
62+
(*entry)->digests = digests;
5363
(*entry)->template_desc = template_desc;
5464
for (i = 0; i < template_desc->num_fields; i++) {
5565
const struct ima_template_field *field =

security/integrity/ima/ima_crypto.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ MODULE_PARM_DESC(ahash_bufsize, "Maximum ahash buffer size");
5757
static struct crypto_shash *ima_shash_tfm;
5858
static struct crypto_ahash *ima_ahash_tfm;
5959

60+
int ima_sha1_idx __ro_after_init;
61+
/*
62+
* Additional number of slots reserved, as needed, for SHA1
63+
* and IMA default algo.
64+
*/
65+
int ima_extra_slots __ro_after_init = 1;
66+
6067
int __init ima_init_crypto(void)
6168
{
6269
long rc;
@@ -502,7 +509,8 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data,
502509
}
503510

504511
if (!rc)
505-
rc = crypto_shash_final(shash, entry->digest);
512+
rc = crypto_shash_final(shash,
513+
entry->digests[ima_sha1_idx].digest);
506514

507515
return rc;
508516
}

security/integrity/ima/ima_fs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ int ima_measurements_show(struct seq_file *m, void *v)
150150
ima_putc(m, &pcr, sizeof(e->pcr));
151151

152152
/* 2nd: template digest */
153-
ima_putc(m, e->digest, TPM_DIGEST_SIZE);
153+
ima_putc(m, e->digests[ima_sha1_idx].digest, TPM_DIGEST_SIZE);
154154

155155
/* 3rd: template name size */
156156
namelen = !ima_canonical_fmt ? strlen(template_name) :
@@ -233,7 +233,7 @@ static int ima_ascii_measurements_show(struct seq_file *m, void *v)
233233
seq_printf(m, "%2d ", e->pcr);
234234

235235
/* 2nd: SHA1 template hash */
236-
ima_print_digest(m, e->digest, TPM_DIGEST_SIZE);
236+
ima_print_digest(m, e->digests[ima_sha1_idx].digest, TPM_DIGEST_SIZE);
237237

238238
/* 3th: template name */
239239
seq_printf(m, " %s", template_name);

security/integrity/ima/ima_queue.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value,
5555
key = ima_hash_key(digest_value);
5656
rcu_read_lock();
5757
hlist_for_each_entry_rcu(qe, &ima_htable.queue[key], hnext) {
58-
rc = memcmp(qe->entry->digest, digest_value, TPM_DIGEST_SIZE);
58+
rc = memcmp(qe->entry->digests[ima_sha1_idx].digest,
59+
digest_value, TPM_DIGEST_SIZE);
5960
if ((rc == 0) && (qe->entry->pcr == pcr)) {
6061
ret = qe;
6162
break;
@@ -75,7 +76,7 @@ static int get_binary_runtime_size(struct ima_template_entry *entry)
7576
int size = 0;
7677

7778
size += sizeof(u32); /* pcr */
78-
size += sizeof(entry->digest);
79+
size += TPM_DIGEST_SIZE;
7980
size += sizeof(int); /* template name size field */
8081
size += strlen(entry->template_desc->name);
8182
size += sizeof(entry->template_data_len);
@@ -107,7 +108,7 @@ static int ima_add_digest_entry(struct ima_template_entry *entry,
107108

108109
atomic_long_inc(&ima_htable.len);
109110
if (update_htable) {
110-
key = ima_hash_key(entry->digest);
111+
key = ima_hash_key(entry->digests[ima_sha1_idx].digest);
111112
hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]);
112113
}
113114

@@ -171,7 +172,8 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
171172

172173
mutex_lock(&ima_extend_list_mutex);
173174
if (!violation) {
174-
memcpy(digest, entry->digest, sizeof(digest));
175+
memcpy(digest, entry->digests[ima_sha1_idx].digest,
176+
sizeof(digest));
175177
if (ima_lookup_digest_entry(digest, entry->pcr)) {
176178
audit_cause = "hash_exists";
177179
result = -EEXIST;

security/integrity/ima/ima_template.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ static int ima_restore_template_data(struct ima_template_desc *template_desc,
301301
int template_data_size,
302302
struct ima_template_entry **entry)
303303
{
304+
struct tpm_digest *digests;
304305
int ret = 0;
305306
int i;
306307

@@ -309,11 +310,21 @@ static int ima_restore_template_data(struct ima_template_desc *template_desc,
309310
if (!*entry)
310311
return -ENOMEM;
311312

313+
digests = kcalloc(NR_BANKS(ima_tpm_chip) + ima_extra_slots,
314+
sizeof(*digests), GFP_NOFS);
315+
if (!digests) {
316+
kfree(*entry);
317+
return -ENOMEM;
318+
}
319+
320+
(*entry)->digests = digests;
321+
312322
ret = ima_parse_buf(template_data, template_data + template_data_size,
313323
NULL, template_desc->num_fields,
314324
(*entry)->template_data, NULL, NULL,
315325
ENFORCE_FIELDS | ENFORCE_BUFEND, "template data");
316326
if (ret < 0) {
327+
kfree((*entry)->digests);
317328
kfree(*entry);
318329
return ret;
319330
}
@@ -445,8 +456,8 @@ int ima_restore_measurement_list(loff_t size, void *buf)
445456
if (ret < 0)
446457
break;
447458

448-
memcpy(entry->digest, hdr[HDR_DIGEST].data,
449-
hdr[HDR_DIGEST].len);
459+
memcpy(entry->digests[ima_sha1_idx].digest,
460+
hdr[HDR_DIGEST].data, hdr[HDR_DIGEST].len);
450461
entry->pcr = !ima_canonical_fmt ? *(hdr[HDR_PCR].data) :
451462
le32_to_cpu(*(hdr[HDR_PCR].data));
452463
ret = ima_restore_measurement_entry(entry);

0 commit comments

Comments
 (0)