From fc92b568890cb21d9cc3fcba1c4918c43e4e9389 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Tue, 12 Aug 2025 23:09:06 +0100 Subject: [PATCH] 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 (cherry picked from commit 4f9f0e504113a9b5c7ce3806d0726d2fb4179422) --- src/ukify/ukify.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/ukify/ukify.py b/src/ukify/ukify.py index 1800259a0f9..40be4adb6bd 100755 --- a/src/ukify/ukify.py +++ b/src/ukify/ukify.py @@ -945,6 +945,19 @@ def pe_add_sections(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 -- 2.47.3