From d4b48cdde1cf27bbd22437a004a7a91d276de19d Mon Sep 17 00:00:00 2001 From: EC2 Default User Date: Sat, 3 Aug 2024 06:58:48 +0000 Subject: [PATCH] add main.rs Signed-off-by: Hiroyuki Moriya <41197469+Gekko0114@users.noreply.github.com> --- experiment/selinux/Cargo.lock | 7 ++++ experiment/selinux/Cargo.toml | 1 + experiment/selinux/README.md | 4 +++ experiment/selinux/src/main.rs | 43 +++++++++++++++++++++++++ experiment/selinux/src/selinux.rs | 18 +++++++---- experiment/selinux/src/selinux_label.rs | 10 ++---- experiment/selinux/src/tools/xattr.rs | 20 ++++++++---- 7 files changed, 82 insertions(+), 21 deletions(-) create mode 100644 experiment/selinux/src/main.rs diff --git a/experiment/selinux/Cargo.lock b/experiment/selinux/Cargo.lock index ca9ba1bd1..5a515cc41 100644 --- a/experiment/selinux/Cargo.lock +++ b/experiment/selinux/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + [[package]] name = "autocfg" version = "1.3.0" @@ -111,6 +117,7 @@ dependencies = [ name = "selinux" version = "0.1.0" dependencies = [ + "anyhow", "nix", "rustix", "tempfile", diff --git a/experiment/selinux/Cargo.toml b/experiment/selinux/Cargo.toml index 35107f76a..785c7cd75 100644 --- a/experiment/selinux/Cargo.toml +++ b/experiment/selinux/Cargo.toml @@ -12,6 +12,7 @@ autoexamples = true keywords = ["youki", "container", "selinux"] [dependencies] +anyhow = "1.0.86" nix = { version = "0.29.0", features = ["process", "fs", "socket"] } rustix = { version = "0.38.34", features = ["fs"] } tempfile = "3.10.1" diff --git a/experiment/selinux/README.md b/experiment/selinux/README.md index d8c1856cd..a47794427 100644 --- a/experiment/selinux/README.md +++ b/experiment/selinux/README.md @@ -6,3 +6,7 @@ Therefore, this PR will implement xattr in Rust. Referenced the implementation of xattr in [unix](golang.org/x/sys/unix) repo. Please import and use this project. + +```console +$ cargo run +``` diff --git a/experiment/selinux/src/main.rs b/experiment/selinux/src/main.rs new file mode 100644 index 000000000..35d5a4e16 --- /dev/null +++ b/experiment/selinux/src/main.rs @@ -0,0 +1,43 @@ +use anyhow::Result; +use selinux::selinux::*; +use selinux::selinux_label::*; +use std::fs::File; +use std::path::Path; + +fn main() -> Result<()> { + let mut selinux_instance: SELinux = SELinux::new(); + + if selinux_instance.get_enabled() { + println!("selinux is enabled"); + } else { + println!("selinux is not enabled"); + + match selinux_instance.set_enforce_mode(SELinuxMode::PERMISSIVE) { + Ok(_) => println!("set selinux mode as permissive"), + Err(e) => println!("{}", e), + } + } + println!( + "default enforce mode is: {}", + selinux_instance.default_enforce_mode() + ); + println!( + "current enforce mode is: {}", + selinux_instance.enforce_mode() + ); + + match selinux_instance.current_label() { + Ok(l) => println!("SELinux label of current process is: {}", l), + Err(e) => println!("{}", e), + } + + let file_path = Path::new("./test_file.txt"); + let _file = File::create(file_path)?; + let selinux_label = + SELinuxLabel::try_from("unconfined_u:object_r:public_content_t:s1".to_string())?; + SELinux::set_file_label(file_path, selinux_label)?; + let current_label = SELinux::file_label(file_path)?; + println!("file label is {}", current_label); + + Ok(()) +} diff --git a/experiment/selinux/src/selinux.rs b/experiment/selinux/src/selinux.rs index e4e911f4a..e724cf997 100644 --- a/experiment/selinux/src/selinux.rs +++ b/experiment/selinux/src/selinux.rs @@ -1,6 +1,6 @@ use crate::selinux_label::SELinuxLabel; use nix::errno::Errno; -use nix::sys::{statfs, statvfs}; +use nix::sys::statfs; use nix::unistd::gettid; use std::collections::HashMap; use std::convert::From; @@ -44,7 +44,12 @@ impl From<&str> for SELinuxMode { impl fmt::Display for SELinuxMode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", *self as i32) + let s = match self { + SELinuxMode::ENFORCING => "enforcing", + SELinuxMode::PERMISSIVE => "permissive", + SELinuxMode::DISABLED => "disabled", + }; + write!(f, "{}", s) } } @@ -211,10 +216,11 @@ impl SELinux { loop { match statfs::statfs(mnt) { Ok(stat) => { - // verify if the file is readonly or not - if !stat.flags().contains(statvfs::FsFlags::ST_RDONLY) { - return false; - } + // In go-selinux, return false if it is not read-only, + // but selinux code in SELinuxProject return true even though it is read-only. + // https://github.com/SELinuxProject/selinux/blob/1f080ffd7ab24b0ad2b46f79db63d62c2ae2747c/libselinux/src/init.c#L44 + // Therefore, this function doesn't check whether it is read-only or not. + // verify if the file is SELinux filesystem return stat.filesystem_type() == statfs::SELINUX_MAGIC; } diff --git a/experiment/selinux/src/selinux_label.rs b/experiment/selinux/src/selinux_label.rs index 717eacc27..04180fec6 100644 --- a/experiment/selinux/src/selinux_label.rs +++ b/experiment/selinux/src/selinux_label.rs @@ -77,10 +77,7 @@ impl SELinux { // When a system call is interrupted by a signal, it needs to be retried. Err(XattrError::EINTR(_)) => continue, Err(e) => { - return Err(SELinuxError::SetFileLabel(format!( - "set_xattr failed: {}", - e - ))); + return Err(SELinuxError::SetFileLabel(e.to_string())); } } } @@ -104,10 +101,7 @@ impl SELinux { // When a system call is interrupted by a signal, it needs to be retried. Err(XattrError::EINTR(_)) => continue, Err(e) => { - return Err(SELinuxError::LSetFileLabel(format!( - "lset_xattr failed: {}", - e - ))); + return Err(SELinuxError::LSetFileLabel(e.to_string())); } } } diff --git a/experiment/selinux/src/tools/xattr.rs b/experiment/selinux/src/tools/xattr.rs index f2b8571e9..2e44ce006 100644 --- a/experiment/selinux/src/tools/xattr.rs +++ b/experiment/selinux/src/tools/xattr.rs @@ -16,6 +16,7 @@ pub enum XattrError { EINTR(i32), } +// SELinux label is not so big, so we allocate 1024 bytes for the buffer. const INITIAL_BUF_SIZE: usize = 1024; pub trait PathXattr { @@ -25,11 +26,15 @@ pub trait PathXattr { fn lget_xattr(&self, attr: &str) -> Result; } -impl PathXattr for Path { +impl

PathXattr for P +where + P: AsRef, +{ // function similar with setxattr in golang.org/x/sys/unix repo. // set_xattr sets extended attributes on a file specified by its path. fn set_xattr(&self, attr: &str, data: &[u8]) -> Result<(), XattrError> { - match rfs::setxattr(self, attr, data, rfs::XattrFlags::CREATE) { + let path = self.as_ref(); + match rfs::setxattr(path, attr, data, rfs::XattrFlags::CREATE) { Ok(_) => Ok(()), Err(e) => { let errno = e.raw_os_error(); @@ -44,7 +49,8 @@ impl PathXattr for Path { // function similar with lsetxattr in golang.org/x/sys/unix repo. // lset_xattr sets extended attributes on a symbolic link. fn lset_xattr(&self, attr: &str, data: &[u8]) -> Result<(), XattrError> { - match rfs::lsetxattr(self, attr, data, rfs::XattrFlags::CREATE) { + let path = self.as_ref(); + match rfs::lsetxattr(path, attr, data, rfs::XattrFlags::CREATE) { Ok(_) => Ok(()), Err(e) => { let errno = e.raw_os_error(); @@ -59,12 +65,12 @@ impl PathXattr for Path { // function similar with getattr in go-selinux repo. // get_xattr returns the value of an extended attribute attr set for path. fn get_xattr(&self, attr: &str) -> Result { - // SELinux label is not so big, so we allocate 1024 bytes for the buffer. + let path = self.as_ref(); let mut buf_size = INITIAL_BUF_SIZE; let mut buf = vec![0u8; buf_size]; loop { - match rfs::getxattr(self, attr, &mut buf) { + match rfs::getxattr(path, attr, &mut buf) { Ok(size) => { if size == buf_size { buf_size *= 2; @@ -85,12 +91,12 @@ impl PathXattr for Path { // function similar with lgetxattr in go-selinux repo. // lget_xattr returns the value of an extended attribute attr set for path. fn lget_xattr(&self, attr: &str) -> Result { - // SELinux label is not so big, so we allocate 1024 bytes for the buffer. + let path = self.as_ref(); let mut buf_size = INITIAL_BUF_SIZE; let mut buf = vec![0u8; buf_size]; loop { - match rfs::lgetxattr(self, attr, &mut buf) { + match rfs::lgetxattr(path, attr, &mut buf) { Ok(size) => { if size == buf_size { buf_size *= 2;