diff --git a/src/boot/stub.c b/src/boot/stub.c index 77678bc796..575b4a982c 100644 --- a/src/boot/stub.c +++ b/src/boot/stub.c @@ -51,7 +51,7 @@ enum { /* magic string to find in the binary image */ DECLARE_NOALLOC_SECTION(".sdmagic", "#### LoaderInfo: systemd-stub " GIT_VERSION " ####"); -DECLARE_SBAT(SBAT_STUB_SECTION_TEXT); +DECLARE_SBAT_PADDED(SBAT_STUB_SECTION_TEXT); static char16_t* pe_section_to_str16( EFI_LOADED_IMAGE_PROTOCOL *loaded_image, diff --git a/src/fundamental/macro-fundamental.h b/src/fundamental/macro-fundamental.h index 7a962df82a..2f2b3df277 100644 --- a/src/fundamental/macro-fundamental.h +++ b/src/fundamental/macro-fundamental.h @@ -421,7 +421,7 @@ assert_cc(sizeof(dummy_t) == 0); /* Restriction/bug (see below) was fixed in GCC 15 and clang 19. */ #if __GNUC__ >= 15 || (defined(__clang__) && __clang_major__ >= 19) -#define DECLARE_FLEX_ARRAY(type, name) type name[] +# define DECLARE_FLEX_ARRAY(type, name) type name[] #else /* Declare a flexible array usable in a union. * This is essentially a work-around for a pointless constraint in C99 @@ -436,17 +436,22 @@ assert_cc(sizeof(dummy_t) == 0); } #endif -/* Declares an ELF read-only string section that does not occupy memory at runtime. */ -#define DECLARE_NOALLOC_SECTION(name, text) \ - asm(".pushsection " name ",\"S\"\n\t" \ - ".ascii " STRINGIFY(text) "\n\t" \ +/* Declare an ELF read-only string section that does not occupy memory at runtime. */ +#define DECLARE_NOALLOC_SECTION(name, text) \ + asm(".pushsection " name ",\"S\"\n\t" \ + ".ascii " STRINGIFY(text) "\n\t" \ ".popsection\n") -#ifdef SBAT_DISTRO - #define DECLARE_SBAT(text) DECLARE_NOALLOC_SECTION(".sbat", text) -#else - #define DECLARE_SBAT(text) -#endif +/* Similar to DECLARE_NOALLOC_SECTION, but pad the section with extra 512 bytes. After taking alignment into + * account, the section has up to 1024 bytes minus the size of the original content of padding, and this + * extra space can be used to extend the contents. This is intended for the .sbat section. */ +#define DECLARE_NOALLOC_SECTION_PADDED(name, text) \ + assert_cc(STRLEN(text) <= 512); \ + asm(".pushsection " name ",\"S\"\n\t" \ + ".ascii " STRINGIFY(text) "\n\t" \ + ".balign 512\n\t" \ + ".fill 512, 1, 0\n\t" \ + ".popsection\n") #define typeof_field(struct_type, member) typeof(((struct_type *) 0)->member) #define sizeof_field(struct_type, member) sizeof(((struct_type *) 0)->member) diff --git a/src/fundamental/sbat.h b/src/fundamental/sbat.h index 9288e05812..1a6e678b35 100644 --- a/src/fundamental/sbat.h +++ b/src/fundamental/sbat.h @@ -12,3 +12,11 @@ SBAT_PROJECT "-stub" ",1,The systemd Developers," SBAT_PROJECT "," PROJECT_VERSION "," PROJECT_URL "\n" \ SBAT_PROJECT "-stub" "." SBAT_DISTRO "," STRINGIFY(SBAT_DISTRO_GENERATION) "," SBAT_DISTRO_SUMMARY "," SBAT_DISTRO_PKGNAME "," SBAT_DISTRO_VERSION "," SBAT_DISTRO_URL "\n" #endif + +#ifdef SBAT_DISTRO +# define DECLARE_SBAT(text) DECLARE_NOALLOC_SECTION(".sbat", text) +# define DECLARE_SBAT_PADDED(text) DECLARE_NOALLOC_SECTION_PADDED(".sbat", text) +#else +# define DECLARE_SBAT(text) +# define DECLARE_SBAT_PADDED(text) +#endif diff --git a/src/ukify/ukify.py b/src/ukify/ukify.py index 2016173855..fce36b6686 100755 --- a/src/ukify/ukify.py +++ b/src/ukify/ukify.py @@ -943,10 +943,10 @@ def pe_add_sections(opts: UkifyConfig, uki: UKI, output: str) -> None: pe.FILE_HEADER.NumberOfSymbols = 0 pe.FILE_HEADER.IMAGE_FILE_LOCAL_SYMS_STRIPPED = True - # Old stubs might have been stripped, leading to unaligned raw data values, so let's fix them up here. # pylint thinks that Structure doesn't have various members that it has… # pylint: disable=no-member + # Old stubs might have been stripped, leading to unaligned raw data values, so let's fix them up here. for i, section in enumerate(pe.sections): oldp = section.PointerToRawData oldsz = section.SizeOfRawData @@ -1045,16 +1045,18 @@ def pe_add_sections(opts: UkifyConfig, uki: UKI, output: str) -> None: for i, s in enumerate(pe.sections[:n_original_sections]): if pe_strip_section_name(s.Name) == section.name and section.name != '.dtbauto': if new_section.Misc_VirtualSize > s.SizeOfRawData: - raise PEError(f'Not enough space in existing section {section.name} to append new data') + raise PEError( + f'Not enough space in existing section {section.name} to append new data' + f' (need {new_section.Misc_VirtualSize}, have {s.SizeOfRawData})' + ) - padding = bytes(new_section.SizeOfRawData - new_section.Misc_VirtualSize) + padding = bytes(s.SizeOfRawData - new_section.Misc_VirtualSize) pe.__data__ = ( pe.__data__[: s.PointerToRawData] + data + padding + pe.__data__[pe.sections[i + 1].PointerToRawData :] ) - s.SizeOfRawData = new_section.SizeOfRawData s.Misc_VirtualSize = new_section.Misc_VirtualSize break else: @@ -1148,10 +1150,12 @@ def merge_sbat(input_pe: list[Path], input_text: list[str]) -> str: continue sbat += split[1:] - return ( - 'sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md\n' - + '\n'.join(sbat) - + '\n\x00' + return '\n'.join( + ( + 'sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md', + *sbat, + '', # an empty line so that we end up with a newline at the end + ) ) @@ -1415,11 +1419,11 @@ def make_uki(opts: UkifyConfig) -> None: for section in opts.sections: uki.add_section(section) - # Don't add a sbat section to profile PE binaries. + # Don't add an .sbat section to profile PE binaries. if (opts.join_profiles or not opts.profile) and not opts.pcrsig: if linux is not None: - # Merge the .sbat sections from stub, kernel and parameter, so that revocation can be done on - # either. + # Merge the .sbat sections from stub, kernel, and parameter, so + # that revocation can be done on either. input_pes = [opts.stub, linux] if not opts.sbat: opts.sbat = [STUB_SBAT]