Skip to content

Commit

Permalink
Changed openat crate to nix's openat.
Browse files Browse the repository at this point in the history
Implemented MountAttrOption enum.

Signed-off-by: higuruchi <[email protected]>
  • Loading branch information
higuruchi committed Dec 11, 2022
1 parent 7c4ff41 commit afa6111
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 81 deletions.
10 changes: 0 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion crates/libcontainer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"] }
Expand Down
5 changes: 2 additions & 3 deletions crates/libcontainer/src/rootfs/mount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
77 changes: 27 additions & 50 deletions crates/libcontainer/src/rootfs/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<linux::MountAttr>,
}

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -199,6 +196,8 @@ pub fn find_parent_mount(rootfs: &Path, mount_infos: Vec<MountInfo>) -> Result<M

#[cfg(test)]
mod tests {
use crate::syscall::linux::MountAttr;

use super::*;
use anyhow::Context;
use oci_spec::runtime::MountBuilder;
Expand Down Expand Up @@ -511,29 +510,7 @@ mod tests {
MountOptionConfig {
flags: MsFlags::empty(),
data: "".to_string(),
rec_attr: Some(linux::MountAttr {
attr_set: linux::MOUNT_ATTR_RDONLY
| linux::MOUNT_ATTR_NOSUID
| linux::MOUNT_ATTR_NODEV
| linux::MOUNT_ATTR_NOEXEC
| linux::MOUNT_ATTR_NODIRATIME
| linux::MOUNT_ATTR_RELATIME
| linux::MOUNT_ATTR_NOATIME
| linux::MOUNT_ATTR_STRICTATIME
| linux::MOUNT_ATTR_NOSYMFOLLOW,
attr_clr: linux::MOUNT_ATTR_RDONLY
| linux::MOUNT_ATTR_NOSUID
| linux::MOUNT_ATTR_NODEV
| linux::MOUNT_ATTR_NOEXEC
| linux::MOUNT_ATTR_NODIRATIME
| linux::MOUNT_ATTR_RELATIME
| linux::MOUNT_ATTR_NOATIME
| linux::MOUNT_ATTR_STRICTATIME
| linux::MOUNT_ATTR_NOSYMFOLLOW
| linux::MOUNT_ATTR__ATIME,
propagation: 0,
userns_fd: 0,
}),
rec_attr: Some(MountAttr::all())
},
mount_option_config
);
Expand Down
172 changes: 155 additions & 17 deletions crates/libcontainer/src/syscall/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ use std::fs;
use std::os::unix::ffi::OsStrExt;
use std::os::unix::fs::symlink;
use std::os::unix::io::RawFd;
use std::str::FromStr;
use std::sync::Arc;
use std::{any::Any, mem, path::Path, ptr};

use anyhow::{anyhow, bail, Context, Result};
use anyhow::{anyhow, bail, Context, Error, Result};
use caps::{CapSet, CapsHashSet};
use libc::{c_char, setdomainname, uid_t};
use nix::fcntl;
Expand All @@ -28,33 +29,169 @@ use super::Syscall;
use crate::syscall::syscall::CloseRange;
use crate::{capabilities, utils};

// Constants used by mount_setattr(2).
pub const MOUNT_ATTR_RDONLY: u64 = 0x00000001; // Mount read-only.
pub const MOUNT_ATTR_NOSUID: u64 = 0x00000002; // Ignore suid and sgid bits.
pub const MOUNT_ATTR_NODEV: u64 = 0x00000004; // Disallow access to device special files.
pub const MOUNT_ATTR_NOEXEC: u64 = 0x00000008; // Disallow program execution.
pub const MOUNT_ATTR__ATIME: u64 = 0x00000070; // Setting on how atime should be updated.
pub const MOUNT_ATTR_RELATIME: u64 = 0x00000000; // - Update atime relative to mtime/ctime.
pub const MOUNT_ATTR_NOATIME: u64 = 0x00000010; // - Do not update access times.
pub const MOUNT_ATTR_STRICTATIME: u64 = 0x00000020; // - Always perform atime updates.
pub const MOUNT_ATTR_NODIRATIME: u64 = 0x00000080; // Do not update directory access times.
pub const MOUNT_ATTR_NOSYMFOLLOW: u64 = 0x00200000; // Prevents following symbolic links.
// Flags used in mount_setattr(2).
// see https://man7.org/linux/man-pages/man2/mount_setattr.2.html.
pub const AT_RECURSIVE: u32 = 0x00008000; // Change the mount properties of the entire mount tree.
pub const MOUNT_ATTR__ATIME: u64 = 0x00000070; // Setting on how atime should be updated.
const MOUNT_ATTR_RDONLY: u64 = 0x00000001;
const MOUNT_ATTR_NOSUID: u64 = 0x00000002;
const MOUNT_ATTR_NODEV: u64 = 0x00000004;
const MOUNT_ATTR_NOEXEC: u64 = 0x00000008;
const MOUNT_ATTR_RELATIME: u64 = 0x00000000;
const MOUNT_ATTR_NOATIME: u64 = 0x00000010;
const MOUNT_ATTR_STRICTATIME: u64 = 0x00000020;
const MOUNT_ATTR_NODIRATIME: u64 = 0x00000080;
const MOUNT_ATTR_NOSYMFOLLOW: u64 = 0x00200000;

/// Constants used by mount_setattr(2).
pub enum MountAttrOption {
/// Mount read-only.
MountArrtRdonly(bool, u64),

/// Ignore suid and sgid bits.
MountAttrNosuid(bool, u64),

/// Disallow access to device special files.
MountAttrNodev(bool, u64),

/// Disallow program execution.
MountAttrNoexec(bool, u64),

/// Setting on how atime should be updated.
MountAttrAtime(bool, u64),

/// Update atime relative to mtime/ctime.
MountAttrRelatime(bool, u64),

/// Do not update access times.
MountAttrNoatime(bool, u64),

/// Always perform atime updates.
MountAttrStrictAtime(bool, u64),

/// Do not update directory access times.
MountAttrNoDiratime(bool, u64),

/// Prevents following symbolic links.
MountAttrNosymfollow(bool, u64),
}

impl FromStr for MountAttrOption {
type Err = Error;

fn from_str(option: &str) -> Result<Self, Self::Err> {
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;
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit afa6111

Please sign in to comment.