]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
ukify: drop NX bit from UKI if kernel doesn't have it
authorLuca Boccassi <luca.boccassi@gmail.com>
Tue, 12 Aug 2025 22:09:06 +0000 (23:09 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 3 Sep 2025 10:10:48 +0000 (12:10 +0200)
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

index 1800259a0f96e90256931141dd6ecbae27c3752d..40be4adb6bdd7d1ecd5fcd31be1512a95e48cb96 100755 (executable)
@@ -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