Skip to content

Commit 858bcec

Browse files
committed
install/bootloader bind-mount rootfs to /run before chrooting
1 parent 0a6fa92 commit 858bcec

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
@@ -10,6 +10,7 @@ use fn_error_context::context;
1010
use bootc_blockdev::{Partition, PartitionTable};
1111
use bootc_mount as mount;
1212
use rustix::mount::UnmountFlags;
13+
use rustix::path::Arg;
1314

1415
use crate::bootc_composefs::boot::{mount_esp, SecurebootKeys};
1516
use crate::{discoverable_partition_specification, utils};
@@ -59,13 +60,18 @@ pub(crate) fn install_via_bootupd(
5960
// When not running inside the target container (through `--src-imgref`) we chroot
6061
// into the deployment before running bootupd. This makes sure we use binaries
6162
// from the target image rather than the buildroot
62-
// But then `/target` (or wherever the user mounted the target FS) is not available,
63-
// but since bootupd use that just to find the underlying device,
64-
// we can use the deployement path just fine.
65-
// Another way of doing this would be to enforce having the target
66-
// rootfs mounted under `/run` so we'd get access to it as part of
67-
// the standard bind-mounts below.
68-
let chroot_root: Option<&str>;
63+
// In some cases (e.g. --write-uuid), bootupd needs to find the underlying device
64+
// for /boot. But since we don't control where the destination rootfs is mounted
65+
// let's bind mount it to a temp mountpoint under /run
66+
// so it gets carried over in the chroot.
67+
68+
let rootfs_mount = if rootfs.starts_with("/run") {
69+
rootfs.to_path_buf().into_std_path_buf()
70+
} else {
71+
let rootfs_mount = tempfile::tempdir_in("/run")?.keep();
72+
rustix::mount::mount_bind_recursive(rootfs.as_std_path(), &rootfs_mount)?;
73+
rootfs_mount
74+
};
6975
let bind_mount_dirs = ["/dev", "/run", "/proc", "/sys"];
7076
let chroot_args = if let Some(target_root) = abs_deployment_path.as_deref() {
7177
tracing::debug!("Setting up bind-mounts before chrooting to the target deployment");
@@ -77,12 +83,10 @@ pub(crate) fn install_via_bootupd(
7783
tracing::debug!("bind mounting {}", dest.display());
7884
rustix::mount::mount_bind_recursive(src, dest)?;
7985
}
80-
chroot_root = Some("/");
8186
// Append the `bootupctl` command, it will be passed as
8287
// an argument to chroot
8388
vec![target_root.as_str(), "bootupctl"]
8489
} else {
85-
chroot_root = None;
8690
vec![]
8791
};
8892

@@ -98,8 +102,7 @@ pub(crate) fn install_via_bootupd(
98102
.args(["backend", "install", "--write-uuid"])
99103
.args(verbose)
100104
.args(bootupd_opts.iter().copied().flatten())
101-
.args(["--device", devpath.as_str()])
102-
.args(chroot_root.or(Some(rootfs.as_str())))
105+
.args(["--device", devpath.as_str(), rootfs_mount.as_str()?])
103106
.log_debug()
104107
.run_inherited_with_cmd_context();
105108

0 commit comments

Comments
 (0)