From: Lennart Poettering Date: Mon, 24 Jun 2024 15:52:10 +0000 (+0200) Subject: efi: introduce PeSectionVector structure, and use it for referencing PE sections X-Git-Tag: v257-rc1~1041^2~27 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fb974ac485c90f9887d5d21ac25d6d26d452eb3c;p=thirdparty%2Fsystemd.git efi: introduce PeSectionVector structure, and use it for referencing PE sections --- diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c index 79de121f0d2..99061a13390 100644 --- a/src/boot/efi/boot.c +++ b/src/boot/efi/boot.c @@ -1855,23 +1855,24 @@ static void generate_boot_entry_titles(Config *config) { } static bool is_sd_boot(EFI_FILE *root_dir, const char16_t *loader_path) { - EFI_STATUS err; static const char * const sections[] = { ".sdmagic", NULL }; - size_t offset = 0, size = 0, read; _cleanup_free_ char *content = NULL; + PeSectionVector vector = {}; + EFI_STATUS err; + size_t read; assert(root_dir); assert(loader_path); - err = pe_file_locate_sections(root_dir, loader_path, sections, &offset, &size); - if (err != EFI_SUCCESS || size != sizeof(SD_MAGIC)) + err = pe_file_locate_sections(root_dir, loader_path, sections, &vector); + if (err != EFI_SUCCESS || vector.size != sizeof(SD_MAGIC)) return false; - err = file_read(root_dir, loader_path, offset, size, &content, &read); - if (err != EFI_SUCCESS || size != read) + err = file_read(root_dir, loader_path, vector.file_offset, vector.size, &content, &read); + if (err != EFI_SUCCESS || vector.size != read) return false; return memcmp(content, SD_MAGIC, sizeof(SD_MAGIC)) == 0; @@ -2104,7 +2105,7 @@ static void config_load_type2_entries( _SECTION_MAX, }; - static const char * const sections[_SECTION_MAX + 1] = { + static const char * const section_names[_SECTION_MAX + 1] = { [SECTION_CMDLINE] = ".cmdline", [SECTION_OSREL] = ".osrel", NULL, @@ -2114,8 +2115,9 @@ static void config_load_type2_entries( *os_image_version = NULL, *os_version = NULL, *os_version_id = NULL, *os_build_id = NULL; const char16_t *good_name, *good_version, *good_sort_key; _cleanup_free_ char *content = NULL; - size_t offs[_SECTION_MAX] = {}, szs[_SECTION_MAX] = {}, pos = 0; + PeSectionVector sections[_SECTION_MAX] = {}; char *line, *key, *value; + size_t pos = 0; err = readdir(linux_dir, &f, &f_size); if (err != EFI_SUCCESS || !f) @@ -2131,11 +2133,16 @@ static void config_load_type2_entries( continue; /* look for .osrel and .cmdline sections in the .efi binary */ - err = pe_file_locate_sections(linux_dir, f->FileName, sections, offs, szs); - if (err != EFI_SUCCESS || szs[SECTION_OSREL] == 0) + err = pe_file_locate_sections(linux_dir, f->FileName, section_names, sections); + if (err != EFI_SUCCESS || !PE_SECTION_VECTOR_IS_SET(sections + SECTION_OSREL)) continue; - err = file_read(linux_dir, f->FileName, offs[SECTION_OSREL], szs[SECTION_OSREL], &content, NULL); + err = file_read(linux_dir, + f->FileName, + sections[SECTION_OSREL].file_offset, + sections[SECTION_OSREL].size, + &content, + NULL); if (err != EFI_SUCCESS) continue; @@ -2206,14 +2213,19 @@ static void config_load_type2_entries( config_add_entry(config, entry); boot_entry_parse_tries(entry, u"\\EFI\\Linux", f->FileName, u".efi"); - if (szs[SECTION_CMDLINE] == 0) + if (!PE_SECTION_VECTOR_IS_SET(sections + SECTION_CMDLINE)) continue; content = mfree(content); /* read the embedded cmdline file */ size_t cmdline_len; - err = file_read(linux_dir, f->FileName, offs[SECTION_CMDLINE], szs[SECTION_CMDLINE], &content, &cmdline_len); + err = file_read(linux_dir, + f->FileName, + sections[SECTION_CMDLINE].file_offset, + sections[SECTION_CMDLINE].size, + &content, + &cmdline_len); if (err == EFI_SUCCESS) { entry->options = xstrn8_to_16(content, cmdline_len); mangle_stub_cmdline(entry->options); diff --git a/src/boot/efi/pe.c b/src/boot/efi/pe.c index cb75c2b42b8..587e3ef7b15 100644 --- a/src/boot/efi/pe.c +++ b/src/boot/efi/pe.c @@ -101,7 +101,7 @@ typedef struct PeOptionalHeader { } _packed_ PeOptionalHeader; typedef struct PeFileHeader { - uint8_t Magic[4]; + uint8_t Magic[4]; CoffFileHeader FileHeader; PeOptionalHeader OptionalHeader; } _packed_ PeFileHeader; @@ -175,48 +175,78 @@ static bool pe_section_name_equal(const char *a, const char *b) { return true; } -static void locate_sections( +static void pe_locate_sections( const PeSectionHeader section_table[], - size_t n_table, + size_t n_section_table, const char * const sections[], - size_t *offsets, - size_t *sizes, - bool in_memory) { + size_t validate_base, + PeSectionVector *ret_sections) { - assert(section_table); + assert(section_table || n_section_table == 0); assert(sections); - assert(offsets); - assert(sizes); + assert(ret_sections); - for (size_t i = 0; i < n_table; i++) { - const PeSectionHeader *sect = section_table + i; + /* Searches for the sections listed in 'sections[]' within the section table. Validates the resulted + * data. If 'validate_base' is non-zero also takes base offset when loaded into memory into account for + * qchecking for overflows. */ - for (size_t j = 0; sections[j]; j++) { - if (!pe_section_name_equal((const char*) sect->Name, sections[j])) + for (size_t i = 0; sections[i]; i++) + FOREACH_ARRAY(j, section_table, n_section_table) { + + if (!pe_section_name_equal((const char*) j->Name, sections[i])) + continue; + + /* Overflow check: ignore sections that are impossibly large, relative to the file + * address for the section. */ + size_t size_max = SIZE_MAX - j->PointerToRawData; + if ((size_t) j->VirtualSize > size_max) + continue; + + /* Overflow check: ignore sections that are impossibly large, given the virtual + * address for the section */ + size_max = SIZE_MAX - j->VirtualAddress; + if (j->VirtualSize > size_max) continue; - offsets[j] = in_memory ? sect->VirtualAddress : sect->PointerToRawData; - sizes[j] = sect->VirtualSize; + /* 2nd overflow check: ignore sections that are impossibly large also taking the + * loaded base into account. */ + if (validate_base != 0) { + if (validate_base > size_max) + continue; + size_max -= validate_base; + + if (j->VirtualAddress > size_max) + continue; + } + + /* At this time, the sizes and offsets have been validated. Store them away */ + ret_sections[i] = (PeSectionVector) { + .size = j->VirtualSize, + .file_offset = j->PointerToRawData, + .memory_offset = j->VirtualAddress, + }; + + /* First matching section wins, ignore the rest */ + break; } - } } static uint32_t get_compatibility_entry_address(const DosFileHeader *dos, const PeFileHeader *pe) { - size_t addr = 0, size = 0; static const char *sections[] = { ".compat", NULL }; + PeSectionVector vector = {}; /* The kernel may provide alternative PE entry points for different PE architectures. This allows * booting a 64-bit kernel on 32-bit EFI that is otherwise running on a 64-bit CPU. The locations of any * such compat entry points are located in a special PE section. */ - locate_sections((const PeSectionHeader *) ((const uint8_t *) dos + section_table_offset(dos, pe)), + pe_locate_sections( + (const PeSectionHeader *) ((const uint8_t *) dos + section_table_offset(dos, pe)), pe->FileHeader.NumberOfSections, sections, - &addr, - &size, - /*in_memory=*/true); + PTR_TO_SIZE(dos), + &vector); - if (size == 0) + if (vector.size == 0) /* not found */ return 0; typedef struct { @@ -226,6 +256,8 @@ static uint32_t get_compatibility_entry_address(const DosFileHeader *dos, const uint32_t entry_point; } _packed_ LinuxPeCompat1; + size_t addr = vector.memory_offset, size = vector.size; + while (size >= sizeof(LinuxPeCompat1) && addr % alignof(LinuxPeCompat1) == 0) { LinuxPeCompat1 *compat = (LinuxPeCompat1 *) ((uint8_t *) dos + addr); @@ -274,15 +306,18 @@ EFI_STATUS pe_kernel_info(const void *base, uint32_t *ret_compat_address) { return EFI_SUCCESS; } -EFI_STATUS pe_memory_locate_sections(const void *base, const char * const sections[], size_t *addrs, size_t *sizes) { +EFI_STATUS pe_memory_locate_sections( + const void *base, + const char* const sections[], + PeSectionVector *ret_sections) { + const DosFileHeader *dos; const PeFileHeader *pe; size_t offset; assert(base); assert(sections); - assert(addrs); - assert(sizes); + assert(ret_sections); dos = (const DosFileHeader *) base; if (!verify_dos(dos)) @@ -293,12 +328,12 @@ EFI_STATUS pe_memory_locate_sections(const void *base, const char * const sectio return EFI_LOAD_ERROR; offset = section_table_offset(dos, pe); - locate_sections((PeSectionHeader *) ((uint8_t *) base + offset), + pe_locate_sections( + (const PeSectionHeader *) ((const uint8_t *) base + offset), pe->FileHeader.NumberOfSections, sections, - addrs, - sizes, - /*in_memory=*/true); + PTR_TO_SIZE(base), + ret_sections); return EFI_SUCCESS; } @@ -307,8 +342,7 @@ EFI_STATUS pe_file_locate_sections( EFI_FILE *dir, const char16_t *path, const char * const sections[], - size_t *offsets, - size_t *sizes) { + PeSectionVector *ret_sections) { _cleanup_free_ PeSectionHeader *section_table = NULL; _cleanup_(file_closep) EFI_FILE *handle = NULL; DosFileHeader dos; @@ -319,8 +353,7 @@ EFI_STATUS pe_file_locate_sections( assert(dir); assert(path); assert(sections); - assert(offsets); - assert(sizes); + assert(ret_sections); err = dir->Open(dir, &handle, (char16_t *) path, EFI_FILE_MODE_READ, 0ULL); if (err != EFI_SUCCESS) @@ -366,8 +399,12 @@ EFI_STATUS pe_file_locate_sections( if (len != section_table_len) return EFI_LOAD_ERROR; - locate_sections(section_table, pe.FileHeader.NumberOfSections, - sections, offsets, sizes, /*in_memory=*/false); + pe_locate_sections( + section_table, + pe.FileHeader.NumberOfSections, + sections, + /* validate_base= */ 0, /* don't validate base */ + ret_sections); return EFI_SUCCESS; } diff --git a/src/boot/efi/pe.h b/src/boot/efi/pe.h index 7e2258fceb9..bc6d74beeb1 100644 --- a/src/boot/efi/pe.h +++ b/src/boot/efi/pe.h @@ -3,17 +3,27 @@ #include "efi.h" +/* This is a subset of the full PE section header structure, with validated values, and without + * the noise. */ +typedef struct PeSectionVector { + size_t size; + size_t memory_offset; /* Offset in memory, relative to base address */ + uint64_t file_offset; /* Offset on disk, relative to beginning of file */ +} PeSectionVector; + +static inline bool PE_SECTION_VECTOR_IS_SET(const PeSectionVector *v) { + return v && v->size != 0; +} + EFI_STATUS pe_memory_locate_sections( const void *base, const char * const sections[], - size_t *addrs, - size_t *sizes); + PeSectionVector *ret_sections); EFI_STATUS pe_file_locate_sections( EFI_FILE *dir, const char16_t *path, const char * const sections[], - size_t *offsets, - size_t *sizes); + PeSectionVector *ret_sections); EFI_STATUS pe_kernel_info(const void *base, uint32_t *ret_compat_address); diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c index f5d2b1d4c54..1375b884369 100644 --- a/src/boot/efi/stub.c +++ b/src/boot/efi/stub.c @@ -413,7 +413,7 @@ static EFI_STATUS load_addons( sort_pointer_array((void**) items, n_items, (compare_pointer_func_t) strcmp16); for (size_t i = 0; i < n_items; i++) { - size_t addrs[_UNIFIED_SECTION_MAX] = {}, szs[_UNIFIED_SECTION_MAX] = {}; + PeSectionVector sections[ELEMENTSOF(unified_sections)] = {}; _cleanup_free_ EFI_DEVICE_PATH *addon_path = NULL; _cleanup_(unload_imagep) EFI_HANDLE addon = NULL; EFI_LOADED_IMAGE_PROTOCOL *loaded_addon = NULL; @@ -441,9 +441,10 @@ static EFI_STATUS load_addons( if (err != EFI_SUCCESS) return log_error_status(err, "Failed to find protocol in %ls: %m", items[i]); - err = pe_memory_locate_sections(loaded_addon->ImageBase, unified_sections, addrs, szs); + err = pe_memory_locate_sections(loaded_addon->ImageBase, unified_sections, sections); if (err != EFI_SUCCESS || - (szs[UNIFIED_SECTION_CMDLINE] == 0 && szs[UNIFIED_SECTION_DTB] == 0)) { + (!PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_CMDLINE) && + !PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_DTB))) { if (err == EFI_SUCCESS) err = EFI_NOT_FOUND; log_error_status(err, @@ -453,38 +454,38 @@ static EFI_STATUS load_addons( } /* We want to enforce that addons are not UKIs, i.e.: they must not embed a kernel. */ - if (szs[UNIFIED_SECTION_LINUX] > 0) { + if (PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_LINUX)) { log_error_status(EFI_INVALID_PARAMETER, "%ls is a UKI, not an addon, ignoring: %m", items[i]); continue; } /* Also enforce that, in case it is specified, .uname matches as a quick way to allow * enforcing compatibility with a specific UKI only */ - if (uname && szs[UNIFIED_SECTION_UNAME] > 0 && + if (uname && PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_UNAME) && !strneq8(uname, - (char *)loaded_addon->ImageBase + addrs[UNIFIED_SECTION_UNAME], - szs[UNIFIED_SECTION_UNAME])) { + (char *)loaded_addon->ImageBase + sections[UNIFIED_SECTION_UNAME].memory_offset, + sections[UNIFIED_SECTION_UNAME].size)) { log_error(".uname mismatch between %ls and UKI, ignoring", items[i]); continue; } - if (ret_cmdline && szs[UNIFIED_SECTION_CMDLINE] > 0) { + if (ret_cmdline && PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_CMDLINE)) { _cleanup_free_ char16_t *tmp = TAKE_PTR(cmdline), - *extra16 = xstrn8_to_16((char *)loaded_addon->ImageBase + addrs[UNIFIED_SECTION_CMDLINE], - szs[UNIFIED_SECTION_CMDLINE]); + *extra16 = xstrn8_to_16((char *)loaded_addon->ImageBase + sections[UNIFIED_SECTION_CMDLINE].memory_offset, + sections[UNIFIED_SECTION_CMDLINE].size); cmdline = xasprintf("%ls%ls%ls", strempty(tmp), isempty(tmp) ? u"" : u" ", extra16); } - if (ret_dt_bases && szs[UNIFIED_SECTION_DTB] > 0) { + if (ret_dt_bases && PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_DTB)) { dt_sizes = xrealloc(dt_sizes, n_dt * sizeof(size_t), (n_dt + 1) * sizeof(size_t)); - dt_sizes[n_dt] = szs[UNIFIED_SECTION_DTB]; + dt_sizes[n_dt] = sections[UNIFIED_SECTION_DTB].size; dt_bases = xrealloc(dt_bases, n_dt * sizeof(void *), (n_dt + 1) * sizeof(void *)); - dt_bases[n_dt] = xmemdup((uint8_t*)loaded_addon->ImageBase + addrs[UNIFIED_SECTION_DTB], + dt_bases[n_dt] = xmemdup((uint8_t*)loaded_addon->ImageBase + sections[UNIFIED_SECTION_DTB].memory_offset, dt_sizes[n_dt]); dt_filenames = xrealloc(dt_filenames, @@ -515,11 +516,11 @@ static EFI_STATUS run(EFI_HANDLE image) { void **dt_bases_addons_global = NULL, **dt_bases_addons_uki = NULL; char16_t **dt_filenames_addons_global = NULL, **dt_filenames_addons_uki = NULL; _cleanup_free_ size_t *dt_sizes_addons_global = NULL, *dt_sizes_addons_uki = NULL; - size_t linux_size, initrd_size, ucode_size, dt_size, n_dts_addons_global = 0, n_dts_addons_uki = 0; - EFI_PHYSICAL_ADDRESS linux_base, initrd_base, ucode_base, dt_base; + size_t linux_size, initrd_size = 0, ucode_size = 0, dt_size = 0, n_dts_addons_global = 0, n_dts_addons_uki = 0; + EFI_PHYSICAL_ADDRESS linux_base, initrd_base = 0, ucode_base = 0, dt_base = 0; _cleanup_(devicetree_cleanup) struct devicetree_state dt_state = {}; EFI_LOADED_IMAGE_PROTOCOL *loaded_image; - size_t addrs[_UNIFIED_SECTION_MAX] = {}, szs[_UNIFIED_SECTION_MAX] = {}; + PeSectionVector sections[ELEMENTSOF(unified_sections)] = {}; _cleanup_free_ char16_t *cmdline = NULL, *cmdline_addons_global = NULL, *cmdline_addons_uki = NULL; int sections_measured = -1, parameters_measured = -1, sysext_measured = -1, confext_measured = -1; _cleanup_free_ char *uname = NULL; @@ -541,8 +542,8 @@ static EFI_STATUS run(EFI_HANDLE image) { (void) process_random_seed(esp_dir); } - err = pe_memory_locate_sections(loaded_image->ImageBase, unified_sections, addrs, szs); - if (err != EFI_SUCCESS || szs[UNIFIED_SECTION_LINUX] == 0) { + err = pe_memory_locate_sections(loaded_image->ImageBase, unified_sections, sections); + if (err != EFI_SUCCESS || !PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_LINUX)) { if (err == EFI_SUCCESS) err = EFI_NOT_FOUND; return log_error_status(err, "Unable to locate embedded .linux section: %m"); @@ -553,9 +554,9 @@ static EFI_STATUS run(EFI_HANDLE image) { CLEANUP_ARRAY(dt_filenames_addons_global, n_dts_addons_global, dt_filenames_free); CLEANUP_ARRAY(dt_filenames_addons_uki, n_dts_addons_uki, dt_filenames_free); - if (szs[UNIFIED_SECTION_UNAME] > 0) - uname = xstrndup8((char *)loaded_image->ImageBase + addrs[UNIFIED_SECTION_UNAME], - szs[UNIFIED_SECTION_UNAME]); + if (PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_UNAME)) + uname = xstrndup8((char *)loaded_image->ImageBase + sections[UNIFIED_SECTION_UNAME].memory_offset, + sections[UNIFIED_SECTION_UNAME].size); /* Now that we have the UKI sections loaded, also load global first and then local (per-UKI) * addons. The data is loaded at once, and then used later. */ @@ -597,7 +598,7 @@ static EFI_STATUS run(EFI_HANDLE image) { if (!unified_section_measure(section)) /* shall not measure? */ continue; - if (szs[section] == 0) /* not found */ + if (!PE_SECTION_VECTOR_IS_SET(sections + section)) /* not found */ continue; /* First measure the name of the section */ @@ -614,11 +615,10 @@ static EFI_STATUS run(EFI_HANDLE image) { m = false; (void) tpm_log_ipl_event_ascii( TPM2_PCR_KERNEL_BOOT, - POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[section], - szs[section], + POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + sections[section].memory_offset, + sections[section].size, unified_sections[section], &m); - combine_measured_flag(§ions_measured, m); } @@ -628,9 +628,10 @@ static EFI_STATUS run(EFI_HANDLE image) { (void) efivar_set_uint_string(MAKE_GUID_PTR(LOADER), u"StubPcrKernelImage", TPM2_PCR_KERNEL_BOOT, 0); /* Show splash screen as early as possible */ - graphics_splash((const uint8_t*) loaded_image->ImageBase + addrs[UNIFIED_SECTION_SPLASH], szs[UNIFIED_SECTION_SPLASH]); + if (PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_SPLASH)) + graphics_splash((const uint8_t*) loaded_image->ImageBase + sections[UNIFIED_SECTION_SPLASH].memory_offset, sections[UNIFIED_SECTION_SPLASH].size); - if (use_load_options(image, loaded_image, szs[UNIFIED_SECTION_CMDLINE] > 0, &cmdline)) { + if (use_load_options(image, loaded_image, /* have_cmdline= */ PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_CMDLINE), &cmdline)) { /* Let's measure the passed kernel command line into the TPM. Note that this possibly * 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 @@ -638,10 +639,10 @@ static EFI_STATUS run(EFI_HANDLE image) { m = false; (void) tpm_log_load_options(cmdline, &m); combine_measured_flag(¶meters_measured, m); - } else if (szs[UNIFIED_SECTION_CMDLINE] > 0) { + } else if (PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_CMDLINE)) { cmdline = xstrn8_to_16( - (char *) loaded_image->ImageBase + addrs[UNIFIED_SECTION_CMDLINE], - szs[UNIFIED_SECTION_CMDLINE]); + (char *) loaded_image->ImageBase + sections[UNIFIED_SECTION_CMDLINE].memory_offset, + sections[UNIFIED_SECTION_CMDLINE].size); mangle_stub_cmdline(cmdline); } @@ -727,8 +728,11 @@ static EFI_STATUS run(EFI_HANDLE image) { &m) == EFI_SUCCESS) combine_measured_flag(&confext_measured, m); - dt_size = szs[UNIFIED_SECTION_DTB]; - dt_base = dt_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[UNIFIED_SECTION_DTB] : 0; + + if (PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_DTB)) { + dt_size = sections[UNIFIED_SECTION_DTB].size; + dt_base = POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + sections[UNIFIED_SECTION_DTB].memory_offset; + } /* First load the base device tree, then fix it up using addons - global first, then per-UKI. */ if (dt_size > 0) { @@ -767,10 +771,10 @@ static EFI_STATUS run(EFI_HANDLE image) { * is not measured, neither as raw section (see above), nor as cpio (here), because it is the * signature of expected PCR values, i.e. its input are PCR measurements, and hence it shouldn't * itself be input for PCR measurements. */ - if (szs[UNIFIED_SECTION_PCRSIG] > 0) + if (PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_PCRSIG)) (void) pack_cpio_literal( - (uint8_t*) loaded_image->ImageBase + addrs[UNIFIED_SECTION_PCRSIG], - szs[UNIFIED_SECTION_PCRSIG], + (uint8_t*) loaded_image->ImageBase + sections[UNIFIED_SECTION_PCRSIG].memory_offset, + sections[UNIFIED_SECTION_PCRSIG].size, ".extra", u"tpm2-pcr-signature.json", /* dir_mode= */ 0555, @@ -785,10 +789,10 @@ static EFI_STATUS run(EFI_HANDLE image) { * a cpio and also pass it to the kernel, so that it can be read from * /.extra/tpm2-pcr-public-key.pem. This section is already measure above, hence we won't measure the * cpio. */ - if (szs[UNIFIED_SECTION_PCRPKEY] > 0) + if (PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_PCRPKEY)) (void) pack_cpio_literal( - (uint8_t*) loaded_image->ImageBase + addrs[UNIFIED_SECTION_PCRPKEY], - szs[UNIFIED_SECTION_PCRPKEY], + (uint8_t*) loaded_image->ImageBase + sections[UNIFIED_SECTION_PCRPKEY].memory_offset, + sections[UNIFIED_SECTION_PCRPKEY].size, ".extra", u"tpm2-pcr-public-key.pem", /* dir_mode= */ 0555, @@ -799,14 +803,18 @@ static EFI_STATUS run(EFI_HANDLE image) { &pcrpkey_initrd_size, /* ret_measured= */ NULL); - linux_size = szs[UNIFIED_SECTION_LINUX]; - linux_base = POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[UNIFIED_SECTION_LINUX]; + linux_size = sections[UNIFIED_SECTION_LINUX].size; + linux_base = POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + sections[UNIFIED_SECTION_LINUX].memory_offset; - initrd_size = szs[UNIFIED_SECTION_INITRD]; - initrd_base = initrd_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[UNIFIED_SECTION_INITRD] : 0; + if (PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_INITRD)) { + initrd_size = sections[UNIFIED_SECTION_INITRD].size; + initrd_base = POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + sections[UNIFIED_SECTION_INITRD].memory_offset; + } - ucode_size = szs[UNIFIED_SECTION_UCODE]; - ucode_base = ucode_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[UNIFIED_SECTION_UCODE] : 0; + if (PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_UCODE)) { + ucode_size = sections[UNIFIED_SECTION_UCODE].size; + ucode_base = POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + sections[UNIFIED_SECTION_UCODE].memory_offset; + } _cleanup_pages_ Pages initrd_pages = {}; if (ucode_base || credential_initrd || global_credential_initrd || sysext_initrd || confext_initrd || pcrsig_initrd || pcrpkey_initrd) { @@ -857,4 +865,4 @@ static EFI_STATUS run(EFI_HANDLE image) { return err; } -DEFINE_EFI_MAIN_FUNCTION(run, "systemd-stub", /*wait_for_debugger=*/false); +DEFINE_EFI_MAIN_FUNCTION(run, "systemd-stub", /* wait_for_debugger= */ false);