From 842952c522e9c0536da532fd7ed0a063a1e93f3b Mon Sep 17 00:00:00 2001 From: Kotaro Inoue Date: Sun, 29 Sep 2024 18:28:27 +0900 Subject: [PATCH 1/4] Define MountOption enum Signed-off-by: Kotaro Inoue --- crates/libcontainer/src/rootfs/utils.rs | 80 ++++++++++---------- crates/libcontainer/src/syscall/linux.rs | 95 ++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 39 deletions(-) diff --git a/crates/libcontainer/src/rootfs/utils.rs b/crates/libcontainer/src/rootfs/utils.rs index a30c0a917..5e22430e3 100644 --- a/crates/libcontainer/src/rootfs/utils.rs +++ b/crates/libcontainer/src/rootfs/utils.rs @@ -6,7 +6,7 @@ use nix::sys::stat::SFlag; use oci_spec::runtime::{LinuxDevice, LinuxDeviceBuilder, LinuxDeviceType, Mount}; use super::mount::MountError; -use crate::syscall::linux::{self, MountRecursive}; +use crate::syscall::linux::{self, MountOption, MountRecursive}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct MountOptionConfig { @@ -131,51 +131,53 @@ pub fn parse_mount(m: &Mount) -> std::result::Result Some((false, MsFlags::empty())), - "ro" => Some((false, MsFlags::MS_RDONLY)), - "rw" => Some((true, MsFlags::MS_RDONLY)), - "suid" => Some((true, MsFlags::MS_NOSUID)), - "nosuid" => Some((false, MsFlags::MS_NOSUID)), - "dev" => Some((true, MsFlags::MS_NODEV)), - "nodev" => Some((false, MsFlags::MS_NODEV)), - "exec" => Some((true, MsFlags::MS_NOEXEC)), - "noexec" => Some((false, MsFlags::MS_NOEXEC)), - "sync" => Some((false, MsFlags::MS_SYNCHRONOUS)), - "async" => Some((true, MsFlags::MS_SYNCHRONOUS)), - "dirsync" => Some((false, MsFlags::MS_DIRSYNC)), - "remount" => Some((false, MsFlags::MS_REMOUNT)), - "mand" => Some((false, MsFlags::MS_MANDLOCK)), - "nomand" => Some((true, MsFlags::MS_MANDLOCK)), - "atime" => Some((true, MsFlags::MS_NOATIME)), - "noatime" => Some((false, MsFlags::MS_NOATIME)), - "diratime" => Some((true, MsFlags::MS_NODIRATIME)), - "nodiratime" => Some((false, MsFlags::MS_NODIRATIME)), - "bind" => Some((false, MsFlags::MS_BIND)), - "rbind" => Some((false, MsFlags::MS_BIND | MsFlags::MS_REC)), - "unbindable" => Some((false, MsFlags::MS_UNBINDABLE)), - "runbindable" => Some((false, MsFlags::MS_UNBINDABLE | MsFlags::MS_REC)), - "private" => Some((true, MsFlags::MS_PRIVATE)), - "rprivate" => Some((true, MsFlags::MS_PRIVATE | MsFlags::MS_REC)), - "shared" => Some((true, MsFlags::MS_SHARED)), - "rshared" => Some((true, MsFlags::MS_SHARED | MsFlags::MS_REC)), - "slave" => Some((true, MsFlags::MS_SLAVE)), - "rslave" => Some((true, MsFlags::MS_SLAVE | MsFlags::MS_REC)), - "relatime" => Some((true, MsFlags::MS_RELATIME)), - "norelatime" => Some((true, MsFlags::MS_RELATIME)), - "strictatime" => Some((true, MsFlags::MS_STRICTATIME)), - "nostrictatime" => Some((true, MsFlags::MS_STRICTATIME)), - unknown => { + if let Some((is_clear, flag)) = match MountOption::from_str(option.as_ref()) { + Ok(v) => match v { + MountOption::Defaults(is_clear, flag) => Some((is_clear, flag)), + MountOption::Ro(is_clear, flag) => Some((is_clear, flag)), + MountOption::Rw(is_clear, flag) => Some((is_clear, flag)), + MountOption::Suid(is_clear, flag) => Some((is_clear, flag)), + MountOption::Nosuid(is_clear, flag) => Some((is_clear, flag)), + MountOption::Dev(is_clear, flag) => Some((is_clear, flag)), + MountOption::Nodev(is_clear, flag) => Some((is_clear, flag)), + MountOption::Exec(is_clear, flag) => Some((is_clear, flag)), + MountOption::Noexec(is_clear, flag) => Some((is_clear, flag)), + MountOption::Sync(is_clear, flag) => Some((is_clear, flag)), + MountOption::Async(is_clear, flag) => Some((is_clear, flag)), + MountOption::Dirsync(is_clear, flag) => Some((is_clear, flag)), + MountOption::Remount(is_clear, flag) => Some((is_clear, flag)), + MountOption::Mand(is_clear, flag) => Some((is_clear, flag)), + MountOption::Nomand(is_clear, flag) => Some((is_clear, flag)), + MountOption::Atime(is_clear, flag) => Some((is_clear, flag)), + MountOption::Noatime(is_clear, flag) => Some((is_clear, flag)), + MountOption::Diratime(is_clear, flag) => Some((is_clear, flag)), + MountOption::Nodiratime(is_clear, flag) => Some((is_clear, flag)), + MountOption::Bind(is_clear, flag) => Some((is_clear, flag)), + MountOption::Rbind(is_clear, flag) => Some((is_clear, flag)), + MountOption::Unbindable(is_clear, flag) => Some((is_clear, flag)), + MountOption::Runbindable(is_clear, flag) => Some((is_clear, flag)), + MountOption::Private(is_clear, flag) => Some((is_clear, flag)), + MountOption::Rprivate(is_clear, flag) => Some((is_clear, flag)), + MountOption::Shared(is_clear, flag) => Some((is_clear, flag)), + MountOption::Rshared(is_clear, flag) => Some((is_clear, flag)), + MountOption::Slave(is_clear, flag) => Some((is_clear, flag)), + MountOption::Rslave(is_clear, flag) => Some((is_clear, flag)), + MountOption::Relatime(is_clear, flag) => Some((is_clear, flag)), + MountOption::Norelatime(is_clear, flag) => Some((is_clear, flag)), + MountOption::Strictatime(is_clear, flag) => Some((is_clear, flag)), + MountOption::Nostrictatime(is_clear, flag) => Some((is_clear, flag)), + }, + Err(unknown) => { if unknown == "idmap" || unknown == "ridmap" { - return Err(MountError::UnsupportedMountOption(unknown.to_string())); + return Err(MountError::UnsupportedMountOption(unknown)); } None } } { if is_clear { - flags &= !flag; + flags.remove(flag); } else { - flags |= flag; + flags.insert(flag); } continue; } diff --git a/crates/libcontainer/src/syscall/linux.rs b/crates/libcontainer/src/syscall/linux.rs index 1b6d702e1..d32c184f6 100644 --- a/crates/libcontainer/src/syscall/linux.rs +++ b/crates/libcontainer/src/syscall/linux.rs @@ -38,6 +38,101 @@ const MOUNT_ATTR_STRICTATIME: u64 = 0x00000020; const MOUNT_ATTR_NODIRATIME: u64 = 0x00000080; const MOUNT_ATTR_NOSYMFOLLOW: u64 = 0x00200000; +/// Constants used by mount(2). +pub enum MountOption { + Defaults(bool, MsFlags), + Ro(bool, MsFlags), + Rw(bool, MsFlags), + Suid(bool, MsFlags), + Nosuid(bool, MsFlags), + Dev(bool, MsFlags), + Nodev(bool, MsFlags), + Exec(bool, MsFlags), + Noexec(bool, MsFlags), + Sync(bool, MsFlags), + Async(bool, MsFlags), + Dirsync(bool, MsFlags), + Remount(bool, MsFlags), + Mand(bool, MsFlags), + Nomand(bool, MsFlags), + Atime(bool, MsFlags), + Noatime(bool, MsFlags), + Diratime(bool, MsFlags), + Nodiratime(bool, MsFlags), + Bind(bool, MsFlags), + Rbind(bool, MsFlags), + Unbindable(bool, MsFlags), + Runbindable(bool, MsFlags), + Private(bool, MsFlags), + Rprivate(bool, MsFlags), + Shared(bool, MsFlags), + Rshared(bool, MsFlags), + Slave(bool, MsFlags), + Rslave(bool, MsFlags), + Relatime(bool, MsFlags), + Norelatime(bool, MsFlags), + Strictatime(bool, MsFlags), + Nostrictatime(bool, MsFlags), +} + +impl FromStr for MountOption { + type Err = String; + + fn from_str(option: &str) -> std::result::Result { + match option { + "defaults" => Ok(MountOption::Defaults(false, MsFlags::empty())), + "ro" => Ok(MountOption::Ro(false, MsFlags::MS_RDONLY)), + "rw" => Ok(MountOption::Rw(true, MsFlags::MS_RDONLY)), + "suid" => Ok(MountOption::Suid(true, MsFlags::MS_NOSUID)), + "nosuid" => Ok(MountOption::Nosuid(false, MsFlags::MS_NOSUID)), + "dev" => Ok(MountOption::Dev(true, MsFlags::MS_NODEV)), + "nodev" => Ok(MountOption::Nodev(false, MsFlags::MS_NODEV)), + "exec" => Ok(MountOption::Exec(true, MsFlags::MS_NOEXEC)), + "noexec" => Ok(MountOption::Noexec(false, MsFlags::MS_NOEXEC)), + "sync" => Ok(MountOption::Sync(false, MsFlags::MS_SYNCHRONOUS)), + "async" => Ok(MountOption::Async(true, MsFlags::MS_SYNCHRONOUS)), + "dirsync" => Ok(MountOption::Dirsync(false, MsFlags::MS_DIRSYNC)), + "remount" => Ok(MountOption::Remount(false, MsFlags::MS_REMOUNT)), + "mand" => Ok(MountOption::Mand(false, MsFlags::MS_MANDLOCK)), + "nomand" => Ok(MountOption::Nomand(true, MsFlags::MS_MANDLOCK)), + "atime" => Ok(MountOption::Atime(true, MsFlags::MS_NOATIME)), + "noatime" => Ok(MountOption::Noatime(false, MsFlags::MS_NOATIME)), + "diratime" => Ok(MountOption::Diratime(true, MsFlags::MS_NODIRATIME)), + "nodiratime" => Ok(MountOption::Nodiratime(false, MsFlags::MS_NODIRATIME)), + "bind" => Ok(MountOption::Bind(false, MsFlags::MS_BIND)), + "rbind" => Ok(MountOption::Rbind( + false, + MsFlags::MS_BIND | MsFlags::MS_REC, + )), + "unbindable" => Ok(MountOption::Unbindable(false, MsFlags::MS_UNBINDABLE)), + "runbindable" => Ok(MountOption::Runbindable( + false, + MsFlags::MS_UNBINDABLE | MsFlags::MS_REC, + )), + "private" => Ok(MountOption::Private(true, MsFlags::MS_PRIVATE)), + "rprivate" => Ok(MountOption::Rprivate( + true, + MsFlags::MS_PRIVATE | MsFlags::MS_REC, + )), + "shared" => Ok(MountOption::Shared(true, MsFlags::MS_SHARED)), + "rshared" => Ok(MountOption::Rshared( + true, + MsFlags::MS_SHARED | MsFlags::MS_REC, + )), + "slave" => Ok(MountOption::Slave(true, MsFlags::MS_SLAVE)), + "rslave" => Ok(MountOption::Rslave( + true, + MsFlags::MS_SLAVE | MsFlags::MS_REC, + )), + "relatime" => Ok(MountOption::Relatime(false, MsFlags::MS_RELATIME)), + "norelatime" => Ok(MountOption::Norelatime(true, MsFlags::MS_RELATIME)), + "strictatime" => Ok(MountOption::Strictatime(false, MsFlags::MS_STRICTATIME)), + "nostrictatime" => Ok(MountOption::Nostrictatime(true, MsFlags::MS_STRICTATIME)), + _ => Err(option.to_string()), + } + } +} + /// Constants used by mount_setattr(2). pub enum MountRecursive { /// Mount read-only. From f2af633145bdfd52ac67e44b7f0f18efd28e7c0d Mon Sep 17 00:00:00 2001 From: Kotaro Inoue Date: Tue, 31 Dec 2024 00:56:01 +0900 Subject: [PATCH 2/4] Fix wrong test cases for mount options Signed-off-by: Kotaro Inoue --- crates/libcontainer/src/rootfs/utils.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/libcontainer/src/rootfs/utils.rs b/crates/libcontainer/src/rootfs/utils.rs index 5e22430e3..4b53c2e55 100644 --- a/crates/libcontainer/src/rootfs/utils.rs +++ b/crates/libcontainer/src/rootfs/utils.rs @@ -245,7 +245,7 @@ mod tests { )?; assert_eq!( MountOptionConfig { - flags: MsFlags::MS_NOSUID, + flags: MsFlags::MS_NOSUID | MsFlags::MS_STRICTATIME, data: "mode=755,size=65536k".to_string(), rec_attr: None, }, @@ -366,7 +366,8 @@ mod tests { flags: MsFlags::MS_NOSUID | MsFlags::MS_NOEXEC | MsFlags::MS_NODEV - | MsFlags::MS_RDONLY, + | MsFlags::MS_RDONLY + | MsFlags::MS_RELATIME, data: "".to_string(), rec_attr: None }, From a53a1249f9f8f91b7a63bd34da6dc66dfa9200aa Mon Sep 17 00:00:00 2001 From: Kotaro Inoue Date: Tue, 31 Dec 2024 02:10:31 +0900 Subject: [PATCH 3/4] Add method to return known options for MountOption Signed-off-by: Kotaro Inoue --- crates/libcontainer/src/syscall/linux.rs | 58 +++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/crates/libcontainer/src/syscall/linux.rs b/crates/libcontainer/src/syscall/linux.rs index d32c184f6..ca1d2828e 100644 --- a/crates/libcontainer/src/syscall/linux.rs +++ b/crates/libcontainer/src/syscall/linux.rs @@ -75,6 +75,50 @@ pub enum MountOption { Nostrictatime(bool, MsFlags), } +impl MountOption { + // Return all possible mount options + pub fn known_options() -> Vec { + [ + "defaults", + "ro", + "rw", + "suid", + "nosuid", + "dev", + "nodev", + "exec", + "noexec", + "sync", + "async", + "dirsync", + "remount", + "mand", + "nomand", + "atime", + "noatime", + "diratime", + "nodiratime", + "bind", + "rbind", + "unbindable", + "runbindable", + "private", + "rprivate", + "shared", + "rshared", + "slave", + "rslave", + "relatime", + "norelatime", + "strictatime", + "nostrictatime", + ] + .iter() + .map(|s| s.to_string()) + .collect() + } +} + impl FromStr for MountOption { type Err = String; @@ -694,12 +738,13 @@ mod tests { use std::fs; use std::os::unix::prelude::AsRawFd; + use std::str::FromStr; use anyhow::{bail, Context, Result}; use nix::{fcntl, sys, unistd}; use serial_test::serial; - use super::LinuxSyscall; + use super::{LinuxSyscall, MountOption}; use crate::syscall::Syscall; #[test] @@ -761,4 +806,15 @@ mod tests { unistd::close(fd)?; Ok(()) } + + #[test] + fn test_known_mount_options_implemented() -> Result<()> { + for option in MountOption::known_options() { + match MountOption::from_str(&option) { + Ok(_) => {} + Err(e) => bail!("failed to parse mount option: {}", e), + } + } + Ok(()) + } } From 33608e38acff233f2124a6055fbcb8c5841bbd50 Mon Sep 17 00:00:00 2001 From: Kotaro Inoue Date: Wed, 15 Jan 2025 23:31:47 +0900 Subject: [PATCH 4/4] Revert unnecessary change Signed-off-by: Kotaro Inoue --- crates/libcontainer/src/rootfs/utils.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/libcontainer/src/rootfs/utils.rs b/crates/libcontainer/src/rootfs/utils.rs index 4b53c2e55..7c847e570 100644 --- a/crates/libcontainer/src/rootfs/utils.rs +++ b/crates/libcontainer/src/rootfs/utils.rs @@ -175,9 +175,9 @@ pub fn parse_mount(m: &Mount) -> std::result::Result