diff options
author | Roberto Sassu <roberto.sassu@huawei.com> | 2017-05-16 08:53:42 -0400 |
---|---|---|
committer | Mimi Zohar <zohar@linux.vnet.ibm.com> | 2017-06-21 14:37:12 -0400 |
commit | 47fdee60b47fc2836b256761ab60ada26788b323 (patch) | |
tree | fb700aa9baec452a54fd4a68c7a9f7f9b4ceed70 | |
parent | b17fd9ecf854e8f695e911d3ff9e1fe33bb1c76c (diff) |
ima: use ima_parse_buf() to parse measurements headers
The binary_hdr_v1 and binary_data_v1 structures defined in
ima_restore_measurement_list() have been replaced with an array of four
ima_field_data structures where pcr, digest, template name and
template data lengths and pointers are stored.
The length of pcr and digest in the ima_field_data array and the bits
in the bitmap are set before ima_parse_buf() is called. The ENFORCE_FIELDS
bit is set for all entries except the last one (there is still data to
parse), and ENFORCE_BUFEND is set only for the last entry.
Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
-rw-r--r-- | security/integrity/ima/ima_template.c | 80 |
1 files changed, 28 insertions, 52 deletions
diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c index cebb37c63629..624e2a1d0f89 100644 --- a/security/integrity/ima/ima_template.c +++ b/security/integrity/ima/ima_template.c | |||
@@ -19,6 +19,9 @@ | |||
19 | #include "ima.h" | 19 | #include "ima.h" |
20 | #include "ima_template_lib.h" | 20 | #include "ima_template_lib.h" |
21 | 21 | ||
22 | enum header_fields { HDR_PCR, HDR_DIGEST, HDR_TEMPLATE_NAME, | ||
23 | HDR_TEMPLATE_DATA, HDR__LAST }; | ||
24 | |||
22 | static struct ima_template_desc builtin_templates[] = { | 25 | static struct ima_template_desc builtin_templates[] = { |
23 | {.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT}, | 26 | {.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT}, |
24 | {.name = "ima-ng", .fmt = "d-ng|n-ng"}, | 27 | {.name = "ima-ng", .fmt = "d-ng|n-ng"}, |
@@ -337,27 +340,19 @@ static int ima_restore_template_data(struct ima_template_desc *template_desc, | |||
337 | /* Restore the serialized binary measurement list without extending PCRs. */ | 340 | /* Restore the serialized binary measurement list without extending PCRs. */ |
338 | int ima_restore_measurement_list(loff_t size, void *buf) | 341 | int ima_restore_measurement_list(loff_t size, void *buf) |
339 | { | 342 | { |
340 | struct binary_hdr_v1 { | ||
341 | u32 pcr; | ||
342 | u8 digest[TPM_DIGEST_SIZE]; | ||
343 | u32 template_name_len; | ||
344 | char template_name[0]; | ||
345 | } __packed; | ||
346 | char template_name[MAX_TEMPLATE_NAME_LEN]; | 343 | char template_name[MAX_TEMPLATE_NAME_LEN]; |
347 | 344 | ||
348 | struct binary_data_v1 { | ||
349 | u32 template_data_size; | ||
350 | char template_data[0]; | ||
351 | } __packed; | ||
352 | |||
353 | struct ima_kexec_hdr *khdr = buf; | 345 | struct ima_kexec_hdr *khdr = buf; |
354 | struct binary_hdr_v1 *hdr_v1; | 346 | struct ima_field_data hdr[HDR__LAST] = { |
355 | struct binary_data_v1 *data_v1; | 347 | [HDR_PCR] = {.len = sizeof(u32)}, |
348 | [HDR_DIGEST] = {.len = TPM_DIGEST_SIZE}, | ||
349 | }; | ||
356 | 350 | ||
357 | void *bufp = buf + sizeof(*khdr); | 351 | void *bufp = buf + sizeof(*khdr); |
358 | void *bufendp; | 352 | void *bufendp; |
359 | struct ima_template_entry *entry; | 353 | struct ima_template_entry *entry; |
360 | struct ima_template_desc *template_desc; | 354 | struct ima_template_desc *template_desc; |
355 | DECLARE_BITMAP(hdr_mask, HDR__LAST); | ||
361 | unsigned long count = 0; | 356 | unsigned long count = 0; |
362 | int ret = 0; | 357 | int ret = 0; |
363 | 358 | ||
@@ -380,6 +375,10 @@ int ima_restore_measurement_list(loff_t size, void *buf) | |||
380 | return -EINVAL; | 375 | return -EINVAL; |
381 | } | 376 | } |
382 | 377 | ||
378 | bitmap_zero(hdr_mask, HDR__LAST); | ||
379 | bitmap_set(hdr_mask, HDR_PCR, 1); | ||
380 | bitmap_set(hdr_mask, HDR_DIGEST, 1); | ||
381 | |||
383 | /* | 382 | /* |
384 | * ima kexec buffer prefix: version, buffer size, count | 383 | * ima kexec buffer prefix: version, buffer size, count |
385 | * v1 format: pcr, digest, template-name-len, template-name, | 384 | * v1 format: pcr, digest, template-name-len, template-name, |
@@ -387,31 +386,25 @@ int ima_restore_measurement_list(loff_t size, void *buf) | |||
387 | */ | 386 | */ |
388 | bufendp = buf + khdr->buffer_size; | 387 | bufendp = buf + khdr->buffer_size; |
389 | while ((bufp < bufendp) && (count++ < khdr->count)) { | 388 | while ((bufp < bufendp) && (count++ < khdr->count)) { |
390 | hdr_v1 = bufp; | 389 | int enforce_mask = ENFORCE_FIELDS; |
391 | if (bufp > (bufendp - sizeof(*hdr_v1))) { | ||
392 | pr_err("attempting to restore partial measurement\n"); | ||
393 | ret = -EINVAL; | ||
394 | break; | ||
395 | } | ||
396 | bufp += sizeof(*hdr_v1); | ||
397 | 390 | ||
398 | if (ima_canonical_fmt) | 391 | enforce_mask |= (count == khdr->count) ? ENFORCE_BUFEND : 0; |
399 | hdr_v1->template_name_len = | 392 | ret = ima_parse_buf(bufp, bufendp, &bufp, HDR__LAST, hdr, NULL, |
400 | le32_to_cpu(hdr_v1->template_name_len); | 393 | hdr_mask, enforce_mask, "entry header"); |
394 | if (ret < 0) | ||
395 | break; | ||
401 | 396 | ||
402 | if ((hdr_v1->template_name_len >= MAX_TEMPLATE_NAME_LEN) || | 397 | if (hdr[HDR_TEMPLATE_NAME].len >= MAX_TEMPLATE_NAME_LEN) { |
403 | (bufp > (bufendp - hdr_v1->template_name_len))) { | ||
404 | pr_err("attempting to restore a template name \ | 398 | pr_err("attempting to restore a template name \ |
405 | that is too long\n"); | 399 | that is too long\n"); |
406 | ret = -EINVAL; | 400 | ret = -EINVAL; |
407 | break; | 401 | break; |
408 | } | 402 | } |
409 | data_v1 = bufp += (u_int8_t)hdr_v1->template_name_len; | ||
410 | 403 | ||
411 | /* template name is not null terminated */ | 404 | /* template name is not null terminated */ |
412 | memcpy(template_name, hdr_v1->template_name, | 405 | memcpy(template_name, hdr[HDR_TEMPLATE_NAME].data, |
413 | hdr_v1->template_name_len); | 406 | hdr[HDR_TEMPLATE_NAME].len); |
414 | template_name[hdr_v1->template_name_len] = 0; | 407 | template_name[hdr[HDR_TEMPLATE_NAME].len] = 0; |
415 | 408 | ||
416 | if (strcmp(template_name, "ima") == 0) { | 409 | if (strcmp(template_name, "ima") == 0) { |
417 | pr_err("attempting to restore an unsupported \ | 410 | pr_err("attempting to restore an unsupported \ |
@@ -441,34 +434,17 @@ int ima_restore_measurement_list(loff_t size, void *buf) | |||
441 | break; | 434 | break; |
442 | } | 435 | } |
443 | 436 | ||
444 | if (bufp > (bufendp - sizeof(data_v1->template_data_size))) { | ||
445 | pr_err("restoring the template data size failed\n"); | ||
446 | ret = -EINVAL; | ||
447 | break; | ||
448 | } | ||
449 | bufp += (u_int8_t) sizeof(data_v1->template_data_size); | ||
450 | |||
451 | if (ima_canonical_fmt) | ||
452 | data_v1->template_data_size = | ||
453 | le32_to_cpu(data_v1->template_data_size); | ||
454 | |||
455 | if (bufp > (bufendp - data_v1->template_data_size)) { | ||
456 | pr_err("restoring the template data failed\n"); | ||
457 | ret = -EINVAL; | ||
458 | break; | ||
459 | } | ||
460 | bufp += data_v1->template_data_size; | ||
461 | |||
462 | ret = ima_restore_template_data(template_desc, | 437 | ret = ima_restore_template_data(template_desc, |
463 | data_v1->template_data, | 438 | hdr[HDR_TEMPLATE_DATA].data, |
464 | data_v1->template_data_size, | 439 | hdr[HDR_TEMPLATE_DATA].len, |
465 | &entry); | 440 | &entry); |
466 | if (ret < 0) | 441 | if (ret < 0) |
467 | break; | 442 | break; |
468 | 443 | ||
469 | memcpy(entry->digest, hdr_v1->digest, TPM_DIGEST_SIZE); | 444 | memcpy(entry->digest, hdr[HDR_DIGEST].data, |
470 | entry->pcr = | 445 | hdr[HDR_DIGEST].len); |
471 | !ima_canonical_fmt ? hdr_v1->pcr : le32_to_cpu(hdr_v1->pcr); | 446 | entry->pcr = !ima_canonical_fmt ? *(hdr[HDR_PCR].data) : |
447 | le32_to_cpu(*(hdr[HDR_PCR].data)); | ||
472 | ret = ima_restore_measurement_entry(entry); | 448 | ret = ima_restore_measurement_entry(entry); |
473 | if (ret < 0) | 449 | if (ret < 0) |
474 | break; | 450 | break; |