From 599fe002a135570406504998dbb7a42dabc963da Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 26 Jul 2022 18:32:21 +0200 Subject: [PATCH] efi: tell userspace where the stub measured the kernel command line/credentials into This is useful for userspace to know, so that policies can be put together safely, matching what the stub actually measured. --- man/systemd-stub.xml | 10 ++++++- src/boot/efi/cpio.c | 24 ++++++++++++++--- src/boot/efi/cpio.h | 4 ++- src/boot/efi/stub.c | 62 ++++++++++++++++++++++++++------------------ 4 files changed, 70 insertions(+), 30 deletions(-) diff --git a/man/systemd-stub.xml b/man/systemd-stub.xml index 92a20e259ed..955fa6f98f4 100644 --- a/man/systemd-stub.xml +++ b/man/systemd-stub.xml @@ -185,7 +185,7 @@ Credentials (synthesized initrd from companion files) - 12 + 9 + 9 + 12 @@ -239,6 +239,14 @@ bootctl1 to view this data. + + + StubPcrKernelParameters + + The PCR register index the kernel command line and credentials are measured into, + formatted as decimal ASCII string (i.e. 12). This variable is set if a measurement + was successfully completed, and remains unset otherwise. + Note that some of the variables above may also be set by the boot loader. The stub will only set diff --git a/src/boot/efi/cpio.c b/src/boot/efi/cpio.c index 693b3816a49..0d41102d2d8 100644 --- a/src/boot/efi/cpio.c +++ b/src/boot/efi/cpio.c @@ -315,7 +315,8 @@ EFI_STATUS pack_cpio( UINTN n_tpm_pcr, const char16_t *tpm_description, void **ret_buffer, - UINTN *ret_buffer_size) { + UINTN *ret_buffer_size, + bool *ret_measured) { _cleanup_(file_closep) EFI_FILE *root = NULL, *extra_dir = NULL; UINTN dirent_size = 0, buffer_size = 0, n_items = 0, n_allocated = 0; @@ -324,6 +325,7 @@ EFI_STATUS pack_cpio( _cleanup_(strv_freep) char16_t **items = NULL; _cleanup_free_ void *buffer = NULL; uint32_t inode = 1; /* inode counter, so that each item gets a new inode */ + int measured = -1; EFI_STATUS err; assert(loaded_image); @@ -432,24 +434,40 @@ EFI_STATUS pack_cpio( return log_error_status_stall(err, L"Failed to pack cpio trailer: %r"); for (UINTN i = 0; i < n_tpm_pcr; i++) { + bool m; + + if (tpm_pcr[i] == UINT32_MAX) /* Disabled */ + continue; + err = tpm_log_event( tpm_pcr[i], POINTER_TO_PHYSICAL_ADDRESS(buffer), buffer_size, tpm_description, - NULL); - if (err != EFI_SUCCESS) + &m); + if (err != EFI_SUCCESS) { log_error_stall(L"Unable to add initrd TPM measurement for PCR %u (%s), ignoring: %r", tpm_pcr[i], tpm_description, err); + measured = false; + continue; + } + + measured = measured < 0 ? m : (measured && m); } *ret_buffer = TAKE_PTR(buffer); *ret_buffer_size = buffer_size; + if (ret_measured) + *ret_measured = measured; + return EFI_SUCCESS; nothing: *ret_buffer = NULL; *ret_buffer_size = 0; + if (ret_measured) + *ret_measured = true; + return EFI_SUCCESS; } diff --git a/src/boot/efi/cpio.h b/src/boot/efi/cpio.h index e3d206d7e89..672a751825f 100644 --- a/src/boot/efi/cpio.h +++ b/src/boot/efi/cpio.h @@ -2,6 +2,7 @@ #pragma once #include +#include #include EFI_STATUS pack_cpio( @@ -15,4 +16,5 @@ EFI_STATUS pack_cpio( UINTN n_tpm_pcr, const char16_t *tpm_description, void **ret_buffer, - UINTN *ret_buffer_size); + UINTN *ret_buffer_size, + bool *ret_measured); diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c index 7f43678cb14..3673d163450 100644 --- a/src/boot/efi/stub.c +++ b/src/boot/efi/stub.c @@ -178,7 +178,9 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { UINTN szs[_SECTION_MAX] = {}; char *cmdline = NULL; _cleanup_free_ char *cmdline_owned = NULL; + int parameters_measured = -1; EFI_STATUS err; + bool m; InitializeLib(image, sys_table); debug_hook(L"systemd-stub"); @@ -223,34 +225,40 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { * duplicates what we already did in the boot menu, if that was already used. However, since * we want the boot menu to support an EFI binary, and want to this stub to be usable from * any boot menu, let's measure things anyway. */ - (void) tpm_log_load_options(loaded_image->LoadOptions, NULL); + m = false; + (void) tpm_log_load_options(loaded_image->LoadOptions, &m); + parameters_measured = m; } export_variables(loaded_image); - (void) pack_cpio(loaded_image, - NULL, - L".cred", - ".extra/credentials", - /* dir_mode= */ 0500, - /* access_mode= */ 0400, - /* tpm_pcr= */ (uint32_t[]) { TPM_PCR_INDEX_KERNEL_PARAMETERS, TPM_PCR_INDEX_KERNEL_PARAMETERS_COMPAT }, - /* n_tpm_pcr= */ 2, - L"Credentials initrd", - &credential_initrd, - &credential_initrd_size); - - (void) pack_cpio(loaded_image, - L"\\loader\\credentials", - L".cred", - ".extra/global_credentials", - /* dir_mode= */ 0500, - /* access_mode= */ 0400, - /* tpm_pcr= */ (uint32_t[]) { TPM_PCR_INDEX_KERNEL_PARAMETERS, TPM_PCR_INDEX_KERNEL_PARAMETERS_COMPAT }, - /* n_tpm_pcr= */ 2, - L"Global credentials initrd", - &global_credential_initrd, - &global_credential_initrd_size); + if (pack_cpio(loaded_image, + NULL, + L".cred", + ".extra/credentials", + /* dir_mode= */ 0500, + /* access_mode= */ 0400, + /* tpm_pcr= */ (uint32_t[]) { TPM_PCR_INDEX_KERNEL_PARAMETERS, TPM_PCR_INDEX_KERNEL_PARAMETERS_COMPAT }, + /* n_tpm_pcr= */ 2, + L"Credentials initrd", + &credential_initrd, + &credential_initrd_size, + &m) == EFI_SUCCESS) + parameters_measured = parameters_measured < 0 ? m : (parameters_measured && m); + + if (pack_cpio(loaded_image, + L"\\loader\\credentials", + L".cred", + ".extra/global_credentials", + /* dir_mode= */ 0500, + /* access_mode= */ 0400, + /* tpm_pcr= */ (uint32_t[]) { TPM_PCR_INDEX_KERNEL_PARAMETERS, TPM_PCR_INDEX_KERNEL_PARAMETERS_COMPAT }, + /* n_tpm_pcr= */ 2, + L"Global credentials initrd", + &global_credential_initrd, + &global_credential_initrd_size, + &m) == EFI_SUCCESS) + parameters_measured = parameters_measured < 0 ? m : (parameters_measured && m); (void) pack_cpio(loaded_image, NULL, @@ -262,7 +270,11 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { /* n_tpm_pcr= */ 1, L"System extension initrd", &sysext_initrd, - &sysext_initrd_size); + &sysext_initrd_size, + NULL); + + if (parameters_measured > 0) + (void) efivar_set_uint_string(LOADER_GUID, L"StubPcrKernelParameters", TPM_PCR_INDEX_KERNEL_PARAMETERS, 0); linux_size = szs[SECTION_LINUX]; linux_base = POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[SECTION_LINUX]; -- 2.39.2