Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

firmware_loader: Use security_post_load_data()

Now that security_post_load_data() is wired up, use it instead
of the NULL file argument style of security_post_read_file(),
and update the security_kernel_load_data() call to indicate that a
security_kernel_post_load_data() call is expected.

Wire up the IMA check to match earlier logic. Perhaps a generalized
change to ima_post_load_data() might look something like this:

return process_buffer_measurement(buf, size,
kernel_load_data_id_str(load_id),
read_idmap[load_id] ?: FILE_CHECK,
0, NULL);

Signed-off-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
Link: https://lore.kernel.org/r/20201002173828.2099543-10-keescook@chromium.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Kees Cook and committed by
Greg Kroah-Hartman
4f2d99b0 b64fcae7

+21 -15
+4 -4
drivers/base/firmware_loader/fallback.c
··· 272 272 dev_err(dev, "%s: map pages failed\n", 273 273 __func__); 274 274 else 275 - rc = security_kernel_post_read_file(NULL, 276 - fw_priv->data, fw_priv->size, 277 - READING_FIRMWARE); 275 + rc = security_kernel_post_load_data(fw_priv->data, 276 + fw_priv->size, 277 + LOADING_FIRMWARE, "blob"); 278 278 279 279 /* 280 280 * Same logic as fw_load_abort, only the DONE bit ··· 613 613 return false; 614 614 615 615 /* Also permit LSMs and IMA to fail firmware sysfs fallback */ 616 - ret = security_kernel_load_data(LOADING_FIRMWARE, false); 616 + ret = security_kernel_load_data(LOADING_FIRMWARE, true); 617 617 if (ret < 0) 618 618 return false; 619 619
+7 -1
drivers/base/firmware_loader/fallback_platform.c
··· 17 17 if (!(opt_flags & FW_OPT_FALLBACK_PLATFORM)) 18 18 return -ENOENT; 19 19 20 - rc = security_kernel_load_data(LOADING_FIRMWARE, false); 20 + rc = security_kernel_load_data(LOADING_FIRMWARE, true); 21 21 if (rc) 22 22 return rc; 23 23 ··· 27 27 28 28 if (fw_priv->data && size > fw_priv->allocated_size) 29 29 return -ENOMEM; 30 + 31 + rc = security_kernel_post_load_data((u8 *)data, size, LOADING_FIRMWARE, 32 + "platform"); 33 + if (rc) 34 + return rc; 35 + 30 36 if (!fw_priv->data) 31 37 fw_priv->data = vmalloc(size); 32 38 if (!fw_priv->data)
+10 -10
security/integrity/ima/ima_main.c
··· 648 648 enum ima_hooks func; 649 649 u32 secid; 650 650 651 - if (!file && read_id == READING_FIRMWARE) { 652 - if ((ima_appraise & IMA_APPRAISE_FIRMWARE) && 653 - (ima_appraise & IMA_APPRAISE_ENFORCE)) { 654 - pr_err("Prevent firmware loading_store.\n"); 655 - return -EACCES; /* INTEGRITY_UNKNOWN */ 656 - } 657 - return 0; 658 - } 659 - 660 651 /* permit signed certs */ 661 652 if (!file && read_id == READING_X509_CERTIFICATE) 662 653 return 0; ··· 697 706 } 698 707 break; 699 708 case LOADING_FIRMWARE: 700 - if (ima_enforce && (ima_appraise & IMA_APPRAISE_FIRMWARE)) { 709 + if (ima_enforce && (ima_appraise & IMA_APPRAISE_FIRMWARE) && !contents) { 701 710 pr_err("Prevent firmware sysfs fallback loading.\n"); 702 711 return -EACCES; /* INTEGRITY_UNKNOWN */ 703 712 } ··· 733 742 enum kernel_load_data_id load_id, 734 743 char *description) 735 744 { 745 + if (load_id == LOADING_FIRMWARE) { 746 + if ((ima_appraise & IMA_APPRAISE_FIRMWARE) && 747 + (ima_appraise & IMA_APPRAISE_ENFORCE)) { 748 + pr_err("Prevent firmware loading_store.\n"); 749 + return -EACCES; /* INTEGRITY_UNKNOWN */ 750 + } 751 + return 0; 752 + } 753 + 736 754 return 0; 737 755 } 738 756