Skip to content

Commit

Permalink
Merge pull request containers#805 from djach7/installToDisk
Browse files Browse the repository at this point in the history
install-to-disk: Check for mounts before install
  • Loading branch information
cgwalters authored Oct 22, 2024
2 parents 33fcf92 + 89588ef commit 4d816fa
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 3 deletions.
1 change: 1 addition & 0 deletions lib/src/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1802,6 +1802,7 @@ fn test_gather_root_args() {
maj_min: "252:4".into(),
options: "rw".into(),
uuid: Some("965eb3c7-5a3f-470d-aaa2-1bcf04334bc6".into()),
children: None,
};
let r = find_root_args_to_inherit(&[], &inspect).unwrap();
assert_eq!(r.mount_spec, "UUID=965eb3c7-5a3f-470d-aaa2-1bcf04334bc6");
Expand Down
6 changes: 6 additions & 0 deletions lib/src/install/baseline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use super::State;
use super::RUN_BOOTC;
use super::RW_KARG;
use crate::mount;
use crate::mount::is_mounted_in_pid1_mountns;
use crate::task::Task;

// This ensures we end up under 512 to be small-sized.
Expand Down Expand Up @@ -162,6 +163,11 @@ pub(crate) fn install_create_rootfs(
// Canonicalize devpath
let devpath: Utf8PathBuf = device.path().into();

// Always disallow writing to mounted device
if is_mounted_in_pid1_mountns(&device.path())? {
anyhow::bail!("Device {} is mounted", device.path())
}

// Handle wiping any existing data
if opts.wipe {
let dev = &opts.device;
Expand Down
41 changes: 38 additions & 3 deletions lib/src/mount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::task::Task;

#[derive(Deserialize, Debug)]
#[serde(rename_all = "kebab-case")]
#[allow(dead_code)]
pub(crate) struct Filesystem {
// Note if you add an entry to this list, you need to change the --output invocation below too
pub(crate) source: String,
Expand All @@ -21,14 +22,15 @@ pub(crate) struct Filesystem {
pub(crate) fstype: String,
pub(crate) options: String,
pub(crate) uuid: Option<String>,
pub(crate) children: Option<Vec<Filesystem>>,
}

#[derive(Deserialize, Debug)]
pub(crate) struct Findmnt {
pub(crate) filesystems: Vec<Filesystem>,
}

fn run_findmnt(args: &[&str], path: &str) -> Result<Filesystem> {
fn run_findmnt(args: &[&str], path: &str) -> Result<Findmnt> {
let o: Findmnt = Command::new("findmnt")
.args([
"-J",
Expand All @@ -40,6 +42,12 @@ fn run_findmnt(args: &[&str], path: &str) -> Result<Filesystem> {
.arg(path)
.log_debug()
.run_and_parse_json()?;
Ok(o)
}

// Retrieve a mounted filesystem from a device given a matching path
fn findmnt_filesystem(args: &[&str], path: &str) -> Result<Filesystem> {
let o = run_findmnt(args, path)?;
o.filesystems
.into_iter()
.next()
Expand All @@ -50,13 +58,40 @@ fn run_findmnt(args: &[&str], path: &str) -> Result<Filesystem> {
/// Inspect a target which must be a mountpoint root - it is an error
/// if the target is not the mount root.
pub(crate) fn inspect_filesystem(path: &Utf8Path) -> Result<Filesystem> {
run_findmnt(&["--mountpoint"], path.as_str())
findmnt_filesystem(&["--mountpoint"], path.as_str())
}

#[context("Inspecting filesystem by UUID {uuid}")]
/// Inspect a filesystem by partition UUID
pub(crate) fn inspect_filesystem_by_uuid(uuid: &str) -> Result<Filesystem> {
run_findmnt(&["--source"], &(format!("UUID={uuid}")))
findmnt_filesystem(&["--source"], &(format!("UUID={uuid}")))
}

// Check if a specified device contains an already mounted filesystem
// in the root mount namespace
pub(crate) fn is_mounted_in_pid1_mountns(path: &str) -> Result<bool> {
let o = run_findmnt(&["-N"], "1")?;

let mounted = o.filesystems.iter().any(|fs| is_source_mounted(path, fs));

Ok(mounted)
}

// Recursively check a given filesystem to see if it contains an already mounted source
pub(crate) fn is_source_mounted(path: &str, mounted_fs: &Filesystem) -> bool {
if mounted_fs.source.contains(path) {
return true;
}

if let Some(ref children) = mounted_fs.children {
for child in children {
if is_source_mounted(path, child) {
return true;
}
}
}

false
}

/// Mount a device to the target path.
Expand Down

0 comments on commit 4d816fa

Please sign in to comment.