Modify the initrd loading sequence so that the contents of the initrd loaded by the EFI stub are measured into the TPM. Note that this also includes the measurement of a zero sized input if the stub's initrd loader fails for any reason, or simply succeeds with no result, which it does for legacy reasons when using the initrd= command line option. Signed-off-by: Ard Biesheuvel <ardb@xxxxxxxxxx> --- drivers/firmware/efi/libstub/efi-stub-helper.c | 53 +++++++++++++++----- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index 72a7e7c4d403..d8cf1911171a 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -625,6 +625,22 @@ efi_status_t efi_load_initrd_cmdline(efi_loaded_image_t *image, load_addr, load_size); } +static const struct { + efi_tcg2_event_t event_data; + u8 description[]; +} initrd_tcg2_event = { + { + sizeof(initrd_tcg2_event), + { + sizeof(initrd_tcg2_event.event_data.event_header), + EFI_TCG2_EVENT_HEADER_VERSION, + 0, + 0 + }, + }, + "Linux initrd" +}; + /** * efi_load_initrd() - Load initial RAM disk * @image: EFI loaded image protocol @@ -641,25 +657,36 @@ efi_status_t efi_load_initrd(efi_loaded_image_t *image, unsigned long soft_limit, unsigned long hard_limit) { + efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID; + efi_tcg2_protocol_t *tcg2 = NULL; efi_status_t status; if (efi_noinitrd) { *load_addr = *load_size = 0; - return EFI_SUCCESS; + status = EFI_SUCCESS; + } else { + status = efi_load_initrd_dev_path(load_addr, load_size, hard_limit); + if (status == EFI_SUCCESS) { + efi_info("Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID device path\n"); + } else if (status == EFI_NOT_FOUND) { + status = efi_load_initrd_cmdline(image, load_addr, load_size, + soft_limit, hard_limit); + if (status == EFI_SUCCESS && *load_size > 0) + efi_info("Loaded initrd from command line option\n"); + } + if (status != EFI_SUCCESS) { + efi_err("Failed to load initrd: 0x%lx\n", status); + *load_addr = *load_size = 0; + } } - status = efi_load_initrd_dev_path(load_addr, load_size, hard_limit); - if (status == EFI_SUCCESS) { - efi_info("Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID device path\n"); - } else if (status == EFI_NOT_FOUND) { - status = efi_load_initrd_cmdline(image, load_addr, load_size, - soft_limit, hard_limit); - if (status == EFI_SUCCESS && *load_size > 0) - efi_info("Loaded initrd from command line option\n"); - } - if (status != EFI_SUCCESS) { - efi_err("Failed to load initrd: 0x%lx\n", status); - *load_addr = *load_size = 0; + efi_bs_call(locate_protocol, &tcg2_guid, NULL, (void **)&tcg2); + if (tcg2) { + efi_status_t s = efi_call_proto(tcg2, hash_log_extend_event, + 0, *load_addr, *load_size, + &initrd_tcg2_event.event_data); + if (s != EFI_SUCCESS) + efi_warn("Failed to measure initrd data into PCR #xx: 0x%lx\n", s); } return status; } -- 2.17.1