Skip to content

Commit 3d7483e

Browse files
committed
install/bootloader bind-mount rootfs to /run before chrooting
1 parent cff0d1f commit 3d7483e

File tree

1 file changed

+14
-11
lines changed

1 file changed

+14
-11
lines changed

crates/lib/src/bootloader.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use fn_error_context::context;
99
use bootc_blockdev::{Partition, PartitionTable};
1010
use bootc_mount as mount;
1111
use rustix::mount::UnmountFlags;
12+
use rustix::path::Arg;
1213

1314
use crate::bootc_composefs::boot::mount_esp;
1415
use crate::{discoverable_partition_specification, utils};
@@ -55,13 +56,18 @@ pub(crate) fn install_via_bootupd(
5556
// When not running inside the target container (through `--src-imgref`) we chroot
5657
// into the deployment before running bootupd. This makes sure we use binaries
5758
// from the target image rather than the buildroot
58-
// But then `/target` (or wherever the user mounted the target FS) is not available,
59-
// but since bootupd use that just to find the underlying device,
60-
// we can use the deployement path just fine.
61-
// Another way of doing this would be to enforce having the target
62-
// rootfs mounted under `/run` so we'd get access to it as part of
63-
// the standard bind-mounts below.
64-
let chroot_root: Option<&str>;
59+
// In some cases (e.g. --write-uuid), bootupd needs to find the underlying device
60+
// for /boot. But since we don't control where the destination rootfs is mounted
61+
// let's bind mount it to a temp mountpoint under /run
62+
// so it gets carried over in the chroot.
63+
64+
let rootfs_mount = if rootfs.starts_with("/run") {
65+
rootfs.to_path_buf().into_std_path_buf()
66+
} else {
67+
let rootfs_mount = tempfile::tempdir_in("/run")?.keep();
68+
rustix::mount::mount_bind_recursive(rootfs.as_std_path(), &rootfs_mount)?;
69+
rootfs_mount
70+
};
6571
let bind_mount_dirs = ["/dev", "/run", "/proc", "/sys"];
6672
let chroot_args = if let Some(target_root) = abs_deployment_path.as_deref() {
6773
tracing::debug!("Setting up bind-mounts before chrooting to the target deployment");
@@ -73,12 +79,10 @@ pub(crate) fn install_via_bootupd(
7379
tracing::debug!("bind mounting {}", dest.display());
7480
rustix::mount::mount_bind_recursive(src, dest)?;
7581
}
76-
chroot_root = Some("/");
7782
// Append the `bootupctl` command, it will be passed as
7883
// an argument to chroot
7984
vec![target_root.as_str(), "bootupctl"]
8085
} else {
81-
chroot_root = None;
8286
vec![]
8387
};
8488

@@ -94,8 +98,7 @@ pub(crate) fn install_via_bootupd(
9498
.args(["backend", "install", "--write-uuid"])
9599
.args(verbose)
96100
.args(bootupd_opts.iter().copied().flatten())
97-
.args(["--device", devpath.as_str()])
98-
.args(chroot_root.or(Some(rootfs.as_str())))
101+
.args(["--device", devpath.as_str(), rootfs_mount.as_str()?])
99102
.log_debug()
100103
.run_inherited_with_cmd_context();
101104

0 commit comments

Comments
 (0)