]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Sign systemd-boot EFI binaries under /usr
authorMichael A Cassaniti <michael@cassaniti.id.au>
Mon, 8 Aug 2022 13:03:37 +0000 (23:03 +1000)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 5 Sep 2022 08:15:11 +0000 (10:15 +0200)
If secure boot signing is enabled with UEFI then `systemd-boot` binaries which
are at `/usr/lib/systemd/boot/efi` should be signed with the same signing key
that is used for EFI binaries within the ESP. In comparison to signed ESP
binaries, the '.signed' extension will be kept.

Without this change, any tool that copies these binaries into the ESP will
(likely) be copying an unsigned copy of `systemd-boot`. The service
`systemd-boot-update.service` is just one example of a service that will
regularly attempt to update `systemd-boot` within the ESP.

mkosi/__init__.py

index eeb5d7ab4823475971e1299946a9f16db090bef2..6ef2c0b119ac212ae07f3eadf8374aa65ae7d29e 100644 (file)
@@ -4041,9 +4041,11 @@ def install_unified_kernel(
 def secure_boot_sign(
     config: MkosiConfig,
     state: MkosiState,
+    directory: Path,
     for_cache: bool,
     cached: bool,
     mount: Callable[[], ContextManager[None]],
+    replace: bool = False,
 ) -> None:
     if state.do_run_build_script:
         return
@@ -4057,28 +4059,27 @@ def secure_boot_sign(
         return
 
     with mount():
-        for path, _, filenames in os.walk(state.root / "efi"):
-            for i in filenames:
-                if not i.endswith(".efi") and not i.endswith(".EFI"):
-                    continue
+        for f in itertools.chain(directory.glob('*.efi'), directory.glob('*.EFI')):
+            if os.path.exists(f"{f}.signed"):
+                MkosiPrinter.info(f"Not overwriting existing signed EFI binary {f}.signed")
+                continue
 
-                with complete_step(f"Signing EFI binary {i} in ESP…"):
-                    p = os.path.join(path, i)
-
-                    run(
-                        [
-                            "sbsign",
-                            "--key",
-                            config.secure_boot_key,
-                            "--cert",
-                            config.secure_boot_certificate,
-                            "--output",
-                            p + ".signed",
-                            p,
-                        ],
-                    )
+            with complete_step(f"Signing EFI binary {f}…"):
+                run(
+                    [
+                        "sbsign",
+                        "--key",
+                        config.secure_boot_key,
+                        "--cert",
+                        config.secure_boot_certificate,
+                        "--output",
+                        f"{f}.signed",
+                        f,
+                    ],
+                )
 
-                    os.rename(p + ".signed", p)
+                if replace:
+                    os.rename(f"{f}.signed", f)
 
 
 def extract_unified_kernel(
@@ -7215,6 +7216,9 @@ def build_image(
                 sshkey = setup_ssh(config, state, for_cache, cached_tree)
                 setup_netdev(config, state, cached_tree)
                 run_postinst_script(config, state, loopdev, for_cache)
+                # Sign systemd-boot / sd-boot EFI binaries
+                secure_boot_sign(config, state, state.root / 'usr/lib/systemd/boot/efi',
+                    for_cache, cached, mount=contextlib.nullcontext)
 
                 if cleanup:
                     remove_packages(config, state.root)
@@ -7267,7 +7271,9 @@ def build_image(
                                         root_read_only=True)
 
             install_unified_kernel(config, state, root_hash, for_cache, cached, mount)
-            secure_boot_sign(config, state, for_cache, cached, mount)
+            # Sign EFI binaries under these directories within the ESP
+            for esp_dir in ['efi/EFI/BOOT', 'efi/EFI/systemd', 'efi/EFI/Linux']:
+                secure_boot_sign(config, state, state.root / esp_dir, for_cache, cached, mount, replace=True)
             split_kernel = (
                 extract_unified_kernel(config, state, for_cache, mount)
                 if config.split_artifacts