diff options
author | Lennart Poettering <lennart@poettering.net> | 2022-09-23 15:45:28 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-23 15:45:28 +0200 |
commit | 6e19a7ce138169ba923caa9b8aa460293bc45451 (patch) | |
tree | c530a1f80073e435f56aa944c38305a70f258d95 /src/boot | |
parent | a9dba3ef5f65e97c212e55973e62f70b7b29706d (diff) | |
parent | fa2eebc7a350adc1c61062818acdd1ea4b2aa3c9 (diff) | |
download | systemd-6e19a7ce138169ba923caa9b8aa460293bc45451.tar.gz |
Merge pull request #24628 from medhefgo/boot-sections
boot: Try to detect overlapping PE sections
Diffstat (limited to 'src/boot')
-rw-r--r-- | src/boot/efi/meson.build | 9 | ||||
-rw-r--r-- | src/boot/efi/pe.c | 28 |
2 files changed, 23 insertions, 14 deletions
diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build index b149735246..1947130919 100644 --- a/src/boot/efi/meson.build +++ b/src/boot/efi/meson.build @@ -199,9 +199,12 @@ efi_cflags = [ ] ) -# On some distros, sd-boot/-stub may trigger some bug somewhere that will cause -# kernel execution to fail. The cause seems to be purely based on code size and -# always compiling with at least -O1 will work around that. +# Our code size has increased enough to possibly create overlapping PE sections +# at sd-stub runtime, which will often enough prevent the image from booting. +# This only happens because the usual instructions for assembling a unified +# kernel image contain hardcoded addresses for section VMAs added in. Until a +# proper solution is in place, we can at least compile with as least -O1 to +# reduce the likelyhood of this happening. # https://github.com/systemd/systemd/issues/24202 efi_cflags += '-O1' diff --git a/src/boot/efi/pe.c b/src/boot/efi/pe.c index 4602827f19..051ea74d42 100644 --- a/src/boot/efi/pe.c +++ b/src/boot/efi/pe.c @@ -142,25 +142,31 @@ static void locate_sections( const PeSectionHeader section_table[], UINTN n_table, const char * const sections[], - UINTN *addrs, UINTN *offsets, - UINTN *sizes) { + UINTN *sizes, + bool in_memory) { assert(section_table); assert(sections); + assert(offsets); assert(sizes); + size_t prev_section_addr = 0; + for (UINTN i = 0; i < n_table; i++) { const PeSectionHeader *sect = section_table + i; + if (in_memory) { + if (prev_section_addr > sect->VirtualAddress) + log_error_stall(u"Overlapping PE sections detected. Boot may fail due to image memory corruption!"); + prev_section_addr = sect->VirtualAddress + sect->VirtualSize; + } + for (UINTN j = 0; sections[j]; j++) { if (memcmp(sect->Name, sections[j], strlen8(sections[j])) != 0) continue; - if (addrs) - addrs[j] = sect->VirtualAddress; - if (offsets) - offsets[j] = sect->PointerToRawData; + offsets[j] = in_memory ? sect->VirtualAddress : sect->PointerToRawData; sizes[j] = sect->VirtualSize; } } @@ -178,8 +184,8 @@ static uint32_t get_compatibility_entry_address(const DosFileHeader *dos, const pe->FileHeader.NumberOfSections, sections, &addr, - NULL, - &size); + &size, + /*in_memory=*/true); if (size == 0) return 0; @@ -274,8 +280,8 @@ EFI_STATUS pe_memory_locate_sections(const void *base, const char * const sectio pe->FileHeader.NumberOfSections, sections, addrs, - NULL, - sizes); + sizes, + /*in_memory=*/true); return EFI_SUCCESS; } @@ -338,7 +344,7 @@ EFI_STATUS pe_file_locate_sections( return EFI_LOAD_ERROR; locate_sections(section_table, pe.FileHeader.NumberOfSections, - sections, NULL, offsets, sizes); + sections, offsets, sizes, /*in_memory=*/false); return EFI_SUCCESS; } |