From 6017eee9ce495d0b12cfe2f6f7569a0808cd672d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 27 Jul 2022 10:58:29 +0200 Subject: [PATCH] boot: move unified kernel PE section definitions into 'fundamental' code Le's share this code between userspace and uefispace. This is useful later when pre-measuring expected PCRs from userspace. --- meson.build | 2 ++ src/boot/efi/stub.c | 59 +++++++++++-------------------------- src/fundamental/meson.build | 1 + src/fundamental/tpm-pcr.c | 15 ++++++++++ src/fundamental/tpm-pcr.h | 14 +++++++++ 5 files changed, 50 insertions(+), 41 deletions(-) create mode 100644 src/fundamental/tpm-pcr.c diff --git a/meson.build b/meson.build index 6bbb2db55d1..bfe6b31b959 100644 --- a/meson.build +++ b/meson.build @@ -310,6 +310,8 @@ conf.set_quoted('STATUS_UNIT_FORMAT_DEFAULT_STR', status_unit_format conf.set10('FIRST_BOOT_FULL_PRESET', get_option('first-boot-full-preset')) +conf.set10('EFI_TPM_PCR_COMPAT', get_option('efi-tpm-pcr-compat')) + ##################################################################### cc = meson.get_compiler('c') diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c index 549f3ce1d5b..c35ee38749b 100644 --- a/src/boot/efi/stub.c +++ b/src/boot/efi/stub.c @@ -149,28 +149,6 @@ static void export_variables(EFI_LOADED_IMAGE_PROTOCOL *loaded_image) { } EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { - - enum Section { - /* This is the canonical order in which we measure the sections. PLEASE DO NOT REORDER! */ - SECTION_LINUX, - SECTION_OSREL, - SECTION_CMDLINE, - SECTION_INITRD, - SECTION_SPLASH, - SECTION_DTB, - _SECTION_MAX, - }; - - static const char * const sections[_SECTION_MAX + 1] = { - [SECTION_LINUX] = ".linux", - [SECTION_OSREL] = ".osrel", - [SECTION_CMDLINE] = ".cmdline", - [SECTION_INITRD] = ".initrd", - [SECTION_SPLASH] = ".splash", - [SECTION_DTB] = ".dtb", - NULL, - }; - UINTN cmdline_len = 0, linux_size, initrd_size, dt_size; UINTN credential_initrd_size = 0, global_credential_initrd_size = 0, sysext_initrd_size = 0; _cleanup_free_ void *credential_initrd = NULL, *global_credential_initrd = NULL; @@ -178,8 +156,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { EFI_PHYSICAL_ADDRESS linux_base, initrd_base, dt_base; _cleanup_(devicetree_cleanup) struct devicetree_state dt_state = {}; EFI_LOADED_IMAGE_PROTOCOL *loaded_image; - UINTN addrs[_SECTION_MAX] = {}; - UINTN szs[_SECTION_MAX] = {}; + UINTN addrs[_UNIFIED_SECTION_MAX] = {}, szs[_UNIFIED_SECTION_MAX] = {}; char *cmdline = NULL; _cleanup_free_ char *cmdline_owned = NULL; int sections_measured = -1, parameters_measured = -1; @@ -201,8 +178,8 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { if (err != EFI_SUCCESS) return log_error_status_stall(err, L"Error getting a LoadedImageProtocol handle: %r", err); - err = pe_memory_locate_sections(loaded_image->ImageBase, sections, addrs, szs); - if (err != EFI_SUCCESS || szs[SECTION_LINUX] == 0) { + err = pe_memory_locate_sections(loaded_image->ImageBase, unified_sections, addrs, szs); + if (err != EFI_SUCCESS || szs[UNIFIED_SECTION_LINUX] == 0) { if (err == EFI_SUCCESS) err = EFI_NOT_FOUND; return log_error_status_stall(err, L"Unable to locate embedded .linux section: %r", err); @@ -211,7 +188,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { /* Measure all "payload" of this PE image into a separate PCR (i.e. where nothing else is written * into so far), so that we have one PCR that we can nicely write policies against because it * contains all static data of this image, and thus can be easily be pre-calculated. */ - for (enum Section section = 0; section < _SECTION_MAX; section++) { + for (UnifiedSection section = 0; section < _UNIFIED_SECTION_MAX; section++) { m = false; if (szs[section] == 0) /* not found */ @@ -220,9 +197,9 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { /* First measure the name of the section */ (void) tpm_log_event_ascii( TPM_PCR_INDEX_KERNEL_IMAGE, - POINTER_TO_PHYSICAL_ADDRESS(sections[section]), - strsize8(sections[section]), /* including NUL byte */ - sections[section], + POINTER_TO_PHYSICAL_ADDRESS(unified_sections[section]), + strsize8(unified_sections[section]), /* including NUL byte */ + unified_sections[section], &m); sections_measured = sections_measured < 0 ? m : (sections_measured && m); @@ -232,7 +209,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { TPM_PCR_INDEX_KERNEL_IMAGE, POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[section], szs[section], - sections[section], + unified_sections[section], &m); sections_measured = sections_measured < 0 ? m : (sections_measured && m); @@ -244,11 +221,11 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { (void) efivar_set_uint_string(LOADER_GUID, L"StubPcrKernelImage", TPM_PCR_INDEX_KERNEL_IMAGE, 0); /* Show splash screen as early as possible */ - graphics_splash((const uint8_t*) loaded_image->ImageBase + addrs[SECTION_SPLASH], szs[SECTION_SPLASH], NULL); + graphics_splash((const uint8_t*) loaded_image->ImageBase + addrs[UNIFIED_SECTION_SPLASH], szs[UNIFIED_SECTION_SPLASH], NULL); - if (szs[SECTION_CMDLINE] > 0) { - cmdline = (char *) loaded_image->ImageBase + addrs[SECTION_CMDLINE]; - cmdline_len = szs[SECTION_CMDLINE]; + if (szs[UNIFIED_SECTION_CMDLINE] > 0) { + cmdline = (char *) loaded_image->ImageBase + addrs[UNIFIED_SECTION_CMDLINE]; + cmdline_len = szs[UNIFIED_SECTION_CMDLINE]; } /* if we are not in secure boot mode, or none was provided, accept a custom command line and replace the built-in one */ @@ -318,14 +295,14 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { if (sysext_measured) (void) efivar_set_uint_string(LOADER_GUID, L"StubPcrInitRDSysExts", TPM_PCR_INDEX_INITRD_SYSEXTS, 0); - linux_size = szs[SECTION_LINUX]; - linux_base = POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[SECTION_LINUX]; + linux_size = szs[UNIFIED_SECTION_LINUX]; + linux_base = POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[UNIFIED_SECTION_LINUX]; - initrd_size = szs[SECTION_INITRD]; - initrd_base = initrd_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[SECTION_INITRD] : 0; + initrd_size = szs[UNIFIED_SECTION_INITRD]; + initrd_base = initrd_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[UNIFIED_SECTION_INITRD] : 0; - dt_size = szs[SECTION_DTB]; - dt_base = dt_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[SECTION_DTB] : 0; + dt_size = szs[UNIFIED_SECTION_DTB]; + dt_base = dt_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[UNIFIED_SECTION_DTB] : 0; if (credential_initrd || global_credential_initrd || sysext_initrd) { /* If we have generated initrds dynamically, let's combine them with the built-in initrd. */ diff --git a/src/fundamental/meson.build b/src/fundamental/meson.build index a4383f6a271..3810d6b456d 100644 --- a/src/fundamental/meson.build +++ b/src/fundamental/meson.build @@ -17,6 +17,7 @@ fundamental_source_paths = files( 'efivars-fundamental.c', 'sha256.c', 'string-util-fundamental.c', + 'tpm-pcr.c', ) # for libbasic diff --git a/src/fundamental/tpm-pcr.c b/src/fundamental/tpm-pcr.c new file mode 100644 index 00000000000..97b3c7b9d2a --- /dev/null +++ b/src/fundamental/tpm-pcr.c @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include + +#include "tpm-pcr.h" + +const char* const unified_sections[_UNIFIED_SECTION_MAX + 1] = { + [UNIFIED_SECTION_LINUX] = ".linux", + [UNIFIED_SECTION_OSREL] = ".osrel", + [UNIFIED_SECTION_CMDLINE] = ".cmdline", + [UNIFIED_SECTION_INITRD] = ".initrd", + [UNIFIED_SECTION_SPLASH] = ".splash", + [UNIFIED_SECTION_DTB] = ".dtb", + NULL, +}; diff --git a/src/fundamental/tpm-pcr.h b/src/fundamental/tpm-pcr.h index 6e8b25934b2..fb0774f70d1 100644 --- a/src/fundamental/tpm-pcr.h +++ b/src/fundamental/tpm-pcr.h @@ -22,3 +22,17 @@ /* This TPM PCR is where we extend the initrd sysext images into which we pass to the booted kernel */ #define TPM_PCR_INDEX_INITRD_SYSEXTS 13U + +/* List of PE sections that have special meaning for us in unified kernels. This is the canonical order in + * which we measure the sections into TPM PCR 11 (see above). PLEASE DO NOT REORDER! */ +typedef enum UnifiedSection { + UNIFIED_SECTION_LINUX, + UNIFIED_SECTION_OSREL, + UNIFIED_SECTION_CMDLINE, + UNIFIED_SECTION_INITRD, + UNIFIED_SECTION_SPLASH, + UNIFIED_SECTION_DTB, + _UNIFIED_SECTION_MAX, +} UnifiedSection; + +extern const char* const unified_sections[_UNIFIED_SECTION_MAX + 1];