diff --git a/src/agent/src/mount.rs b/src/agent/src/mount.rs index f2dd9de3ab..1602d7ac43 100644 --- a/src/agent/src/mount.rs +++ b/src/agent/src/mount.rs @@ -15,7 +15,7 @@ use std::str::FromStr; use std::sync::Arc; use anyhow::{anyhow, Context, Result}; -use kata_sys_util::mount::{create_mount_destination, get_linux_mount_info}; +use kata_sys_util::mount::{create_mount_destination, get_linux_mount_info, parse_mount_options}; use kata_types::mount::{KATA_MOUNT_OPTION_FS_GID, KATA_SHAREDFS_GUEST_PREMOUNT_TAG}; use nix::mount::MsFlags; use nix::unistd::{Gid, Uid}; @@ -49,47 +49,6 @@ const RO_MASK: u32 = 0o440; const EXEC_MASK: u32 = 0o110; const MODE_SETGID: u32 = 0o2000; -#[rustfmt::skip] -lazy_static! { - pub static ref FLAGS: HashMap<&'static str, (bool, MsFlags)> = { - let mut m = HashMap::new(); - m.insert("defaults", (false, MsFlags::empty())); - m.insert("ro", (false, MsFlags::MS_RDONLY)); - m.insert("rw", (true, MsFlags::MS_RDONLY)); - m.insert("suid", (true, MsFlags::MS_NOSUID)); - m.insert("nosuid", (false, MsFlags::MS_NOSUID)); - m.insert("dev", (true, MsFlags::MS_NODEV)); - m.insert("nodev", (false, MsFlags::MS_NODEV)); - m.insert("exec", (true, MsFlags::MS_NOEXEC)); - m.insert("noexec", (false, MsFlags::MS_NOEXEC)); - m.insert("sync", (false, MsFlags::MS_SYNCHRONOUS)); - m.insert("async", (true, MsFlags::MS_SYNCHRONOUS)); - m.insert("dirsync", (false, MsFlags::MS_DIRSYNC)); - m.insert("remount", (false, MsFlags::MS_REMOUNT)); - m.insert("mand", (false, MsFlags::MS_MANDLOCK)); - m.insert("nomand", (true, MsFlags::MS_MANDLOCK)); - m.insert("atime", (true, MsFlags::MS_NOATIME)); - m.insert("noatime", (false, MsFlags::MS_NOATIME)); - m.insert("diratime", (true, MsFlags::MS_NODIRATIME)); - m.insert("nodiratime", (false, MsFlags::MS_NODIRATIME)); - m.insert("bind", (false, MsFlags::MS_BIND)); - m.insert("rbind", (false, MsFlags::MS_BIND | MsFlags::MS_REC)); - m.insert("unbindable", (false, MsFlags::MS_UNBINDABLE)); - m.insert("runbindable", (false, MsFlags::MS_UNBINDABLE | MsFlags::MS_REC)); - m.insert("private", (false, MsFlags::MS_PRIVATE)); - m.insert("rprivate", (false, MsFlags::MS_PRIVATE | MsFlags::MS_REC)); - m.insert("shared", (false, MsFlags::MS_SHARED)); - m.insert("rshared", (false, MsFlags::MS_SHARED | MsFlags::MS_REC)); - m.insert("slave", (false, MsFlags::MS_SLAVE)); - m.insert("rslave", (false, MsFlags::MS_SLAVE | MsFlags::MS_REC)); - m.insert("relatime", (false, MsFlags::MS_RELATIME)); - m.insert("norelatime", (true, MsFlags::MS_RELATIME)); - m.insert("strictatime", (false, MsFlags::MS_STRICTATIME)); - m.insert("nostrictatime", (true, MsFlags::MS_STRICTATIME)); - m - }; -} - #[derive(Debug, PartialEq)] pub struct InitMount<'a> { fstype: &'a str, @@ -168,16 +127,12 @@ pub fn baremount( } let destination_str = destination.to_string_lossy(); - let mut already_mounted = false; if let Ok(m) = get_linux_mount_info(destination_str.deref()) { if m.fs_type == fs_type { - already_mounted = true; + slog_info!(logger, "{source:?} is already mounted at {destination:?}"); + return Ok(()); } } - if already_mounted { - slog_info!(logger, "{source:?} is already mounted at {destination:?}"); - return Ok(()); - } info!( logger, @@ -275,11 +230,12 @@ pub async fn update_ephemeral_mounts( // assume that fsGid has already been set let mount_path = Path::new(&storage.mount_point); let src_path = Path::new(&storage.source); - let opts = storage + let opts: Vec<&String> = storage .options .iter() - .filter(|&opt| !opt.starts_with(FS_GID_EQ)); - let (flags, options) = parse_mount_flags_and_options(opts); + .filter(|&opt| !opt.starts_with(FS_GID_EQ)) + .collect(); + let (flags, options) = parse_mount_options(&opts)?; info!(logger, "mounting storage"; "mount-source" => src_path.display(), @@ -646,7 +602,7 @@ fn mount_storage(logger: &Logger, storage: &Storage) -> Result<()> { return Ok(()); } - let (flags, options) = parse_mount_flags_and_options(&storage.options); + let (flags, options) = parse_mount_options(&storage.options)?; let mount_path = Path::new(&storage.mount_point); let src_path = Path::new(&storage.source); create_mount_destination(src_path, mount_path, "", &storage.fstype) @@ -765,42 +721,6 @@ pub fn is_mounted(mount_point: &str) -> Result { Ok(found) } -#[instrument] -fn parse_mount_flags_and_options( - opts_iter: impl Iterator> + Debug, -) -> (MsFlags, String) { - let mut flags = MsFlags::empty(); - let mut options: String = "".to_string(); - - for opt in opts_iter { - let opt = opt.as_ref(); - if !opt.is_empty() { - match FLAGS.get(opt) { - Some(x) => { - let (clear, f) = *x; - if clear { - flags &= !f; - } else { - flags |= f; - } - } - None => { - if opt.starts_with("io.katacontainers.") { - continue; - } - - if !options.is_empty() { - options.push_str(format!(",{}", opt).as_str()); - } else { - options.push_str(opt); - } - } - }; - } - } - (flags, options) -} - // add_storages takes a list of storages passed by the caller, and perform the // associated operations such as waiting for the device to show up, and mount // it to a specific location, according to the type of handler chosen, and for @@ -878,27 +798,23 @@ pub async fn add_storages( #[instrument] fn mount_to_rootfs(logger: &Logger, m: &InitMount) -> Result<()> { - let (flags, options) = parse_mount_flags_and_options(m.options.iter()); - fs::create_dir_all(m.dest).context("could not create directory")?; + let (flags, options) = parse_mount_options(&m.options)?; let source = Path::new(m.src); let dest = Path::new(m.dest); baremount(source, dest, m.fstype, flags, &options, logger).or_else(|e| { - if m.src != "dev" { - return Err(e); + if m.src == "dev" { + error!( + logger, + "Could not mount filesystem from {} to {}", m.src, m.dest + ); + Ok(()) + } else { + Err(e) } - - error!( - logger, - "Could not mount filesystem from {} to {}", m.src, m.dest - ); - - Ok(()) - })?; - - Ok(()) + }) } #[instrument] @@ -932,13 +848,10 @@ pub fn get_mount_fs_type_from_file(mount_file: &str, mount_point: &str) -> Resul // Read the file line by line using the lines() iterator from std::io::BufRead. for (_index, line) in content.lines().enumerate() { - let capes = match re.captures(line) { - Some(c) => c, - None => continue, - }; - - if capes.len() > 1 { - return Ok(capes[1].to_string()); + if let Some(capes) = re.captures(line) { + if capes.len() > 1 { + return Ok(capes[1].to_string()); + } } } @@ -1971,7 +1884,7 @@ mod tests { for (i, d) in tests.iter().enumerate() { let msg = format!("test[{}]: {:?}", i, d); - let result = parse_mount_flags_and_options(d.options_vec.iter()); + let result = parse_mount_options(&d.options_vec)?; let msg = format!("{}: result: {:?}", msg, result); diff --git a/src/agent/src/namespace.rs b/src/agent/src/namespace.rs index a3ad266162..bf24cd1048 100644 --- a/src/agent/src/namespace.rs +++ b/src/agent/src/namespace.rs @@ -7,14 +7,14 @@ use anyhow::{anyhow, Result}; use nix::mount::MsFlags; use nix::sched::{unshare, CloneFlags}; use nix::unistd::{getpid, gettid}; +use slog::Logger; use std::fmt; use std::fs; use std::fs::File; use std::path::{Path, PathBuf}; use tracing::instrument; -use crate::mount::{baremount, FLAGS}; -use slog::Logger; +use crate::mount::baremount; const PERSISTENT_NS_DIR: &str = "/var/run/sandbox-ns"; pub const NSTYPEIPC: &str = "ipc"; @@ -116,15 +116,7 @@ impl Namespace { // Bind mount the new namespace from the current thread onto the mount point to persist it. let mut flags = MsFlags::empty(); - - if let Some(x) = FLAGS.get("rbind") { - let (clear, f) = *x; - if clear { - flags &= !f; - } else { - flags |= f; - } - }; + flags |= MsFlags::MS_BIND | MsFlags::MS_REC; baremount(source, destination, "none", flags, "", &logger).map_err(|e| { anyhow!( diff --git a/src/libs/kata-sys-util/src/mount.rs b/src/libs/kata-sys-util/src/mount.rs index 522ce3acb1..e649ab436d 100644 --- a/src/libs/kata-sys-util/src/mount.rs +++ b/src/libs/kata-sys-util/src/mount.rs @@ -390,19 +390,17 @@ fn do_rebind_mount>(path: P, readonly: bool, flags: MsFlags) -> R } /// Take fstab style mount options and parses them for use with a standard mount() syscall. -fn parse_mount_options(options: &[String]) -> Result<(MsFlags, String)> { +pub fn parse_mount_options>(options: &[T]) -> Result<(MsFlags, String)> { let mut flags: MsFlags = MsFlags::empty(); let mut data: Vec = Vec::new(); for opt in options.iter() { - if opt == "defaults" { - continue; - } else if opt == "loop" { + if opt.as_ref() == "loop" { return Err(Error::InvalidMountOption("loop".to_string())); - } else if let Some(v) = parse_mount_flags(flags, opt) { + } else if let Some(v) = parse_mount_flags(flags, opt.as_ref()) { flags = v; } else { - data.push(opt.clone()); + data.push(opt.as_ref().to_string()); } } @@ -441,6 +439,7 @@ fn parse_mount_flags(mut flags: MsFlags, flag_str: &str) -> Option { // overridden by subsequent options, as in the option line users,exec,dev,suid). match flag_str { // Clear flags + "defaults" => {} "async" => flags &= !MsFlags::MS_SYNCHRONOUS, "atime" => flags &= !MsFlags::MS_NOATIME, "dev" => flags &= !MsFlags::MS_NODEV, @@ -464,6 +463,14 @@ fn parse_mount_flags(mut flags: MsFlags, flag_str: &str) -> Option { "noexec" => flags |= MsFlags::MS_NOEXEC, "nosuid" => flags |= MsFlags::MS_NOSUID, "rbind" => flags |= MsFlags::MS_BIND | MsFlags::MS_REC, + "unbindable" => flags |= MsFlags::MS_UNBINDABLE, + "runbindable" => flags |= MsFlags::MS_UNBINDABLE | MsFlags::MS_REC, + "private" => flags |= MsFlags::MS_PRIVATE, + "rprivate" => flags |= MsFlags::MS_PRIVATE | MsFlags::MS_REC, + "shared" => flags |= MsFlags::MS_SHARED, + "rshared" => flags |= MsFlags::MS_SHARED | MsFlags::MS_REC, + "slave" => flags |= MsFlags::MS_SLAVE, + "rslave" => flags |= MsFlags::MS_SLAVE | MsFlags::MS_REC, "relatime" => flags |= MsFlags::MS_RELATIME, "remount" => flags |= MsFlags::MS_REMOUNT, "ro" => flags |= MsFlags::MS_RDONLY, @@ -1030,7 +1037,7 @@ mod tests { #[test] fn test_parse_mount_options() { - let options = vec![]; + let options: Vec<&str> = vec![]; let (flags, data) = parse_mount_options(&options).unwrap(); assert!(flags.is_empty()); assert!(data.is_empty());