Add padding to sbat section (#38621)

This commit is contained in:
Luca Boccassi
2025-08-19 17:49:07 +01:00
committed by GitHub
4 changed files with 39 additions and 22 deletions
+1 -1
View File
@@ -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,
+15 -10
View File
@@ -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)
+8
View File
@@ -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
+15 -11
View File
@@ -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]