diff --git a/lib/src/install.rs b/lib/src/install.rs index 96002fb6..abcd775c 100644 --- a/lib/src/install.rs +++ b/lib/src/install.rs @@ -1177,6 +1177,9 @@ pub(crate) async fn install_to_disk(mut opts: InstallToDiskOpts) -> Result<()> { block_opts.device ); } + if !crate::mount::is_same_as_host(Utf8Path::new("/dev"))? { + anyhow::bail!("Add `-v /dev:/dev` to `podman` when using --via-loopback"); + } } else if !target_blockdev_meta.file_type().is_block_device() { anyhow::bail!("Not a block device: {}", block_opts.device); } diff --git a/lib/src/mount.rs b/lib/src/mount.rs index 431d4f13..93938ae7 100644 --- a/lib/src/mount.rs +++ b/lib/src/mount.rs @@ -57,3 +57,24 @@ pub(crate) fn mount(dev: &str, target: &Utf8Path) -> Result<()> { [dev, target.as_str()], ) } + +/// If the fsid of the passed path matches the fsid of the same path rooted +/// at /proc/1/root, it is assumed that these are indeed the same mounted +/// filesystem between container and host. +/// Path *should not* include a leading '/'. It will be stripped. +#[context("Comparing filesystems at {path} and /proc/1/root/{path}")] +pub(crate) fn is_same_as_host(path: &Utf8Path) -> Result { + let path = Utf8Path::new("/").join(path); + + // Using statvfs instead of fs, since rustix will translate the fsid field + // for us. + let devstat = rustix::fs::statvfs(path.as_std_path())?; + let hostpath = Utf8Path::new("/proc/1/root").join(path.strip_prefix("/")?); + let hostdevstat = rustix::fs::statvfs(hostpath.as_std_path())?; + tracing::trace!( + "base mount id {:?}, host mount id {:?}", + devstat.f_fsid, + hostdevstat.f_fsid + ); + Ok(devstat.f_fsid == hostdevstat.f_fsid) +}