summaryrefslogtreecommitdiff
path: root/src/boot
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2022-09-23 15:45:28 +0200
committerGitHub <noreply@github.com>2022-09-23 15:45:28 +0200
commit6e19a7ce138169ba923caa9b8aa460293bc45451 (patch)
treec530a1f80073e435f56aa944c38305a70f258d95 /src/boot
parenta9dba3ef5f65e97c212e55973e62f70b7b29706d (diff)
parentfa2eebc7a350adc1c61062818acdd1ea4b2aa3c9 (diff)
downloadsystemd-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.build9
-rw-r--r--src/boot/efi/pe.c28
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;
}