]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Make sure mkosi works in the initramfs
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 22 Jul 2024 13:19:16 +0000 (15:19 +0200)
committerJörg Behrmann <behrmann@physik.fu-berlin.de>
Mon, 22 Jul 2024 18:47:47 +0000 (20:47 +0200)
bubblewrap uses pivot_root() which doesn't work in the initramfs as
pivot_root() requires / to be a mountpoint which is not the case in
the initramfs. So, to make sure mkosi works from within the initramfs,
let's make / a mountpoint by recursively bind-mounting / (the directory)
to another location and then switching root into the bind mount directory.

mkosi/__init__.py

index faafce049ea56587be1da55f056b7f61876c5aeb..a987a6c6a023c50009bf3829f4418cc3fbc8c2dd 100644 (file)
@@ -4756,6 +4756,34 @@ def run_build(args: Args, config: Config, *, resources: Path, package_dir: Optio
             build_image(Context(args, config, workspace=workspace, resources=resources, package_dir=package_dir))
 
 
+def ensure_root_is_mountpoint() -> None:
+    """
+    bubblewrap uses pivot_root() which doesn't work in the initramfs as pivot_root() requires / to be a mountpoint
+    which is not the case in the initramfs. So, to make sure mkosi works from within the initramfs, let's make / a
+    mountpoint by recursively bind-mounting / (the directory) to another location and then switching root into the bind
+    mount directory.
+    """
+    fstype = run(
+        ["findmnt", "--target", "/", "--output", "FSTYPE", "--noheadings"],
+        stdout=subprocess.PIPE,
+    ).stdout.strip()
+
+    if fstype != "rootfs":
+        return
+
+    if os.getuid() != 0:
+        die("mkosi can only be run as root from the initramfs")
+
+    unshare(CLONE_NEWNS)
+    run(["mount", "--make-rslave", "/"])
+    mountpoint = Path("/run/mkosi/mkosi-root")
+    mountpoint.mkdir(parents=True, exist_ok=True)
+    run(["mount", "--rbind", "/", mountpoint])
+    os.chdir(mountpoint)
+    run(["mount", "--move", ".", "/"])
+    os.chroot(".")
+
+
 def run_verb(args: Args, images: Sequence[Config], *, resources: Path) -> None:
     images = list(images)
 
@@ -4800,6 +4828,8 @@ def run_verb(args: Args, images: Sequence[Config], *, resources: Path) -> None:
         page(text, args.pager)
         return
 
+    ensure_root_is_mountpoint()
+
     if args.verb in (Verb.journalctl, Verb.coredumpctl, Verb.ssh):
         # We don't use a tools tree for verbs that don't need an image build.
         last = dataclasses.replace(images[-1], tools_tree=None)