Skip to content

Commit

Permalink
add main.rs
Browse files Browse the repository at this point in the history
Signed-off-by: Hiroyuki Moriya <[email protected]>
  • Loading branch information
EC2 Default User committed Aug 3, 2024
1 parent f0da9cb commit d4b48cd
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 21 deletions.
7 changes: 7 additions & 0 deletions experiment/selinux/Cargo.lock

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

1 change: 1 addition & 0 deletions experiment/selinux/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
4 changes: 4 additions & 0 deletions experiment/selinux/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
```
43 changes: 43 additions & 0 deletions experiment/selinux/src/main.rs
Original file line number Diff line number Diff line change
@@ -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(())
}
18 changes: 12 additions & 6 deletions experiment/selinux/src/selinux.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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)
}
}

Expand Down Expand Up @@ -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;
}
Expand Down
10 changes: 2 additions & 8 deletions experiment/selinux/src/selinux_label.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()));
}
}
}
Expand All @@ -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()));
}
}
}
Expand Down
20 changes: 13 additions & 7 deletions experiment/selinux/src/tools/xattr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -25,11 +26,15 @@ pub trait PathXattr {
fn lget_xattr(&self, attr: &str) -> Result<String, XattrError>;
}

impl PathXattr for Path {
impl<P> PathXattr for P
where
P: AsRef<Path>,
{
// 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();
Expand All @@ -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();
Expand All @@ -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<String, XattrError> {
// 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;
Expand All @@ -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<String, XattrError> {
// 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;
Expand Down

0 comments on commit d4b48cd

Please sign in to comment.