From: Luca Boccassi Date: Tue, 12 Aug 2025 22:09:06 +0000 (+0100) Subject: ukify: drop NX bit from UKI if kernel doesn't have it X-Git-Tag: v258-rc3~44 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4f9f0e504113a9b5c7ce3806d0726d2fb4179422;p=thirdparty%2Fsystemd.git ukify: drop NX bit from UKI if kernel doesn't have it If the kernel is not NX_COMPAT ready (W^X memory compatible) then the UKI should not be marked as NX_COMPAT ready either, as the kernel section is the loadable code in the image. https://microsoft.github.io/mu/WhatAndWhy/enhancedmemoryprotection/ https://www.kraxel.org/blog/2023/12/uefi-nx-linux-boot/ While the sd-stub EFI code itself is NX ready, it is more useful to think of it as one unit of execution together with the kernel it embeds, as that's what it is used for. Fixes https://github.com/systemd/systemd/issues/38545 --- diff --git a/src/ukify/ukify.py b/src/ukify/ukify.py index 8a8d72429fe..a09ea09f9ed 100755 --- a/src/ukify/ukify.py +++ b/src/ukify/ukify.py @@ -1023,6 +1023,19 @@ def pe_add_sections(opts: UkifyConfig, uki: UKI, output: str) -> None: if section.name == '.linux': # Old kernels that use EFI handover protocol will be executed inline. new_section.IMAGE_SCN_CNT_CODE = True + + # Check if the kernel PE has the NX_COMPAT flag set, if not strip it from the UKI as they need + # to have the same value, otherwise when firmwares start enforcing it, booting will fail. + # https://microsoft.github.io/mu/WhatAndWhy/enhancedmemoryprotection/ + # https://www.kraxel.org/blog/2023/12/uefi-nx-linux-boot/ + try: + inner_pe = pefile.PE(data=data, fast_load=True) + nxbit = pefile.DLL_CHARACTERISTICS['IMAGE_DLLCHARACTERISTICS_NX_COMPAT'] + if not inner_pe.OPTIONAL_HEADER.DllCharacteristics & nxbit: + pe.OPTIONAL_HEADER.DllCharacteristics &= ~nxbit + except pefile.PEFormatError: + # Unit tests build images with bogus data + print(f'{section.name} in {uki.executable} is not a valid PE, ignoring', file=sys.stderr) else: new_section.IMAGE_SCN_CNT_INITIALIZED_DATA = True