diff --git a/Cargo.lock b/Cargo.lock index ff84387c64..4f393797d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1247,7 +1247,6 @@ dependencies = [ "mio", "nix", "oci-spec", - "openat", "path-clean", "prctl", "procfs", @@ -1638,15 +1637,6 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" -[[package]] -name = "openat" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95aa7c05907b3ebde2610d602f4ddd992145cc6a84493647c30396f30ba83abe" -dependencies = [ - "libc", -] - [[package]] name = "os_str_bytes" version = "6.4.1" diff --git a/crates/libcontainer/Cargo.toml b/crates/libcontainer/Cargo.toml index 6719d01cf0..e44bcf4937 100644 --- a/crates/libcontainer/Cargo.toml +++ b/crates/libcontainer/Cargo.toml @@ -45,7 +45,6 @@ rust-criu = "0.2.0" wasmer = { version = "2.2.0", optional = true } wasmer-wasi = { version = "2.3.0", optional = true } wasmedge-sdk = { version = "0.7.1", optional = true } -openat = "0.1.21" [dev-dependencies] oci-spec = { version = "0.5.8", features = ["proptests", "runtime"] } diff --git a/crates/libcontainer/src/rootfs/mount.rs b/crates/libcontainer/src/rootfs/mount.rs index 417de6d7eb..1dc0cc533a 100644 --- a/crates/libcontainer/src/rootfs/mount.rs +++ b/crates/libcontainer/src/rootfs/mount.rs @@ -12,9 +12,8 @@ use anyhow::{bail, Context, Result}; use libcgroups::common::CgroupSetup::{Hybrid, Legacy, Unified}; #[cfg(feature = "v1")] use libcgroups::common::DEFAULT_CGROUP_ROOT; -use nix::{errno::Errno, mount::MsFlags}; +use nix::{dir::Dir, errno::Errno, fcntl::OFlag, mount::MsFlags, sys::stat::Mode}; use oci_spec::runtime::{Mount as SpecMount, MountBuilder as SpecMountBuilder}; -use openat::Dir; use procfs::process::{MountInfo, MountOptFields, Process}; use std::fs::{canonicalize, create_dir_all, OpenOptions}; use std::mem; @@ -463,7 +462,7 @@ impl Mount { } if let Some(mount_attr) = &mount_option_config.rec_attr { - let open_dir = Dir::open(dest)?; + let open_dir = Dir::open(dest, OFlag::O_DIRECTORY, Mode::empty())?; let dir_fd_pathbuf = PathBuf::from(format!("/proc/self/fd/{}", open_dir.as_raw_fd())); self.syscall.mount_setattr( -1, diff --git a/crates/libcontainer/src/rootfs/utils.rs b/crates/libcontainer/src/rootfs/utils.rs index 612e0b6251..6adff2c4f1 100644 --- a/crates/libcontainer/src/rootfs/utils.rs +++ b/crates/libcontainer/src/rootfs/utils.rs @@ -2,17 +2,22 @@ use anyhow::{anyhow, Result}; use nix::{mount::MsFlags, sys::stat::SFlag, NixPath}; use oci_spec::runtime::{LinuxDevice, LinuxDeviceBuilder, LinuxDeviceType, Mount}; use procfs::process::MountInfo; -use std::path::{Path, PathBuf}; +use std::{ + path::{Path, PathBuf}, + str::FromStr, +}; -use crate::syscall::linux; +use crate::syscall::linux::{self, MountAttrOption}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct MountOptionConfig { - // Mount Flags. + /// Mount Flags. pub flags: MsFlags, - // Mount data applied to the mount. + + /// Mount data applied to the mount. pub data: String, - // RecAttr represents mount properties to be applied recrusively. + + /// RecAttr represents mount properties to be applied recrusively. pub rec_attr: Option, } @@ -129,28 +134,20 @@ pub fn parse_mount(m: &Mount) -> MountOptionConfig { continue; } - if let Some((is_clear, flag)) = match s.as_str() { - "rro" => Some((false, linux::MOUNT_ATTR_RDONLY)), - "rrw" => Some((true, linux::MOUNT_ATTR_RDONLY)), - "rnosuid" => Some((false, linux::MOUNT_ATTR_NOSUID)), - "rsuid" => Some((true, linux::MOUNT_ATTR_NOSUID)), - "rnodev" => Some((false, linux::MOUNT_ATTR_NODEV)), - "rdev" => Some((true, linux::MOUNT_ATTR_NODEV)), - "rnoexec" => Some((false, linux::MOUNT_ATTR_NOEXEC)), - "rexec" => Some((true, linux::MOUNT_ATTR_NOEXEC)), - "rnodiratime" => Some((false, linux::MOUNT_ATTR_NODIRATIME)), - "rdiratime" => Some((true, linux::MOUNT_ATTR_NODIRATIME)), - "rrelatime" => Some((false, linux::MOUNT_ATTR_RELATIME)), - "rnorelatime" => Some((true, linux::MOUNT_ATTR_RELATIME)), - "rnoatime" => Some((false, linux::MOUNT_ATTR_NOATIME)), - "ratime" => Some((true, linux::MOUNT_ATTR_NOATIME)), - "rstrictatime" => Some((false, linux::MOUNT_ATTR_STRICTATIME)), - "rnostrictatime" => Some((true, linux::MOUNT_ATTR_STRICTATIME)), - "rnosymfollow" => Some((false, linux::MOUNT_ATTR_NOSYMFOLLOW)), - "rsymfollow" => Some((true, linux::MOUNT_ATTR_NOSYMFOLLOW)), - // No support for MOUNT_ATTR_IDMAP yet (needs UserNS FD) - _ => None, - } { + if let Ok(mount_attr_option) = linux::MountAttrOption::from_str(s.as_str()) { + let (is_clear, flag) = match mount_attr_option { + MountAttrOption::MountArrtRdonly(is_clear, flag) => (is_clear, flag), + MountAttrOption::MountAttrNosuid(is_clear, flag) => (is_clear, flag), + MountAttrOption::MountAttrNodev(is_clear, flag) => (is_clear, flag), + MountAttrOption::MountAttrNoexec(is_clear, flag) => (is_clear, flag), + MountAttrOption::MountAttrAtime(is_clear, flag) => (is_clear, flag), + MountAttrOption::MountAttrRelatime(is_clear, flag) => (is_clear, flag), + MountAttrOption::MountAttrNoatime(is_clear, flag) => (is_clear, flag), + MountAttrOption::MountAttrStrictAtime(is_clear, flag) => (is_clear, flag), + MountAttrOption::MountAttrNoDiratime(is_clear, flag) => (is_clear, flag), + MountAttrOption::MountAttrNosymfollow(is_clear, flag) => (is_clear, flag), + }; + if mount_attr.is_none() { mount_attr = Some(linux::MountAttr { attr_set: 0, @@ -199,6 +196,8 @@ pub fn find_parent_mount(rootfs: &Path, mount_infos: Vec) -> Result Result { + match option { + "rro" => return Ok(MountAttrOption::MountArrtRdonly(false, MOUNT_ATTR_RDONLY)), + "rrw" => return Ok(MountAttrOption::MountArrtRdonly(true, MOUNT_ATTR_RDONLY)), + "rnosuid" => return Ok(MountAttrOption::MountAttrNosuid(false, MOUNT_ATTR_NOSUID)), + "rsuid" => return Ok(MountAttrOption::MountAttrNosuid(true, MOUNT_ATTR_NOSUID)), + "rnodev" => return Ok(MountAttrOption::MountAttrNodev(false, MOUNT_ATTR_NODEV)), + "rdev" => return Ok(MountAttrOption::MountAttrNodev(true, MOUNT_ATTR_NODEV)), + "rnoexec" => return Ok(MountAttrOption::MountAttrNoexec(false, MOUNT_ATTR_NOEXEC)), + "rexec" => return Ok(MountAttrOption::MountAttrNoexec(true, MOUNT_ATTR_NOEXEC)), + "rnodiratime" => { + return Ok(MountAttrOption::MountAttrNoDiratime( + false, + MOUNT_ATTR_NODIRATIME, + )) + } + "rdiratime" => { + return Ok(MountAttrOption::MountAttrNoDiratime( + true, + MOUNT_ATTR_NODIRATIME, + )) + } + "rrelatime" => { + return Ok(MountAttrOption::MountAttrRelatime( + false, + MOUNT_ATTR_RELATIME, + )) + } + "rnorelatime" => { + return Ok(MountAttrOption::MountAttrRelatime( + true, + MOUNT_ATTR_RELATIME, + )) + } + "rnoatime" => return Ok(MountAttrOption::MountAttrNoatime(false, MOUNT_ATTR_NOATIME)), + "ratime" => return Ok(MountAttrOption::MountAttrNoatime(true, MOUNT_ATTR_NOATIME)), + "rstrictatime" => { + return Ok(MountAttrOption::MountAttrStrictAtime( + false, + MOUNT_ATTR_STRICTATIME, + )) + } + "rnostrictatime" => { + return Ok(MountAttrOption::MountAttrStrictAtime( + true, + MOUNT_ATTR_STRICTATIME, + )) + } + "rnosymfollow" => { + return Ok(MountAttrOption::MountAttrNosymfollow( + false, + MOUNT_ATTR_NOSYMFOLLOW, + )) + } + "rsymfollow" => { + return Ok(MountAttrOption::MountAttrNosymfollow( + true, + MOUNT_ATTR_NOSYMFOLLOW, + )) + } + // No support for MOUNT_ATTR_IDMAP yet (needs UserNS FD) + _ => bail!("Unexpected option."), + } + } +} #[repr(C)] #[derive(Debug, Clone, PartialEq, Eq)] -// A structure used as te third argument of mount_setattr(2). +/// A structure used as te third argument of mount_setattr(2). pub struct MountAttr { - // Mount properties to set. + /// Mount properties to set. pub attr_set: u64, - // Mount properties to clear. + + /// Mount properties to clear. pub attr_clr: u64, - // Mount propagation type. + + /// Mount propagation type. pub propagation: u64, - // User namespace file descriptor. + + /// User namespace file descriptor. pub userns_fd: u64, } +impl MountAttr { + /// Return MountAttr with the flag raised. + /// This function is used in test code. + pub fn all() -> Self { + MountAttr { + attr_set: MOUNT_ATTR_RDONLY + | MOUNT_ATTR_NOSUID + | MOUNT_ATTR_NODEV + | MOUNT_ATTR_NOEXEC + | MOUNT_ATTR_NODIRATIME + | MOUNT_ATTR_RELATIME + | MOUNT_ATTR_NOATIME + | MOUNT_ATTR_STRICTATIME + | MOUNT_ATTR_NOSYMFOLLOW, + attr_clr: MOUNT_ATTR_RDONLY + | MOUNT_ATTR_NOSUID + | MOUNT_ATTR_NODEV + | MOUNT_ATTR_NOEXEC + | MOUNT_ATTR_NODIRATIME + | MOUNT_ATTR_RELATIME + | MOUNT_ATTR_NOATIME + | MOUNT_ATTR_STRICTATIME + | MOUNT_ATTR_NOSYMFOLLOW + | MOUNT_ATTR__ATIME, + propagation: 0, + userns_fd: 0, + } + } +} + /// Empty structure to implement Command trait for #[derive(Clone)] pub struct LinuxSyscall; @@ -378,6 +515,7 @@ impl Syscall for LinuxSyscall { None => bail!("Invalid filename"), }; let result = unsafe { + // TODO: nix/libc crate hasn't supported mount_setattr system call yet. syscall!( Sysno::mount_setattr, dirfd,