Skip to content

Commit

Permalink
add rsuid and rnosymfollow
Browse files Browse the repository at this point in the history
Signed-off-by: lengrongfu <1275177125@qq.com>
  • Loading branch information
lengrongfu committed Mar 19, 2023
1 parent 4015e9e commit 07c3548
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ use oci_spec::runtime::{
};
use std::collections::hash_set::HashSet;
use std::fs;
use std::fs::File;
use std::os::unix::fs::symlink;
use std::os::unix::prelude::PermissionsExt;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str::FromStr;
use test_framework::{Test, TestGroup, TestResult};

Expand Down Expand Up @@ -202,6 +205,40 @@ fn check_recursive_nosuid() -> TestResult {
result
}

fn check_recursive_rsuid() -> TestResult {
let rsuid_dir_path = PathBuf::from_str("/tmp/rsuid_dir").unwrap();
let mount_dest_path = PathBuf::from_str("/mnt/rsuid_dir").unwrap();
fs::create_dir_all(rsuid_dir_path.clone()).unwrap();

let mount_options = vec!["rbind".to_string(), "rsuid".to_string()];
let mut mount_spec = Mount::default();
mount_spec
.set_destination(mount_dest_path)
.set_typ(None)
.set_source(Some(rsuid_dir_path.clone()))
.set_options(Some(mount_options));
let spec = get_spec(
vec![mount_spec],
vec!["runtimetest".to_string(), "mounts_recursive".to_string()],
);
let result = test_inside_container(spec, &|_| {
// touch /tmp/rsuid_dir/file
let original_file_path = format!("{}/{}", rsuid_dir_path.to_str().unwrap(), "file");
File::create(original_file_path.clone())?;
// chmod +s /tmp/rsuid_dir/file && chmod +g /tmp/rsuid_dir/file
Command::new("chmod")
.args(["+s", original_file_path.as_str()])
.output()?;
Command::new("chmod")
.args(["+g", original_file_path.as_str()])
.output()?;

Ok(())
});
fs::remove_dir_all(rsuid_dir_path).unwrap();
result
}

fn check_recursive_noexec() -> TestResult {
let rnoexec_test_base_dir = PathBuf::from_str("/tmp").unwrap();
let rnoexec_dir_path = rnoexec_test_base_dir.join("rnoexec_dir");
Expand Down Expand Up @@ -492,6 +529,46 @@ fn check_recursive_rstrictatime() -> TestResult {
result
}

fn check_recursive_rnosymfollow() -> TestResult {
let rnosymfollow_dir_path = PathBuf::from_str("/tmp/rnosymfollow").unwrap();
let mount_dest_path = PathBuf::from_str("/mnt/rnosymfollow").unwrap();
fs::create_dir_all(rnosymfollow_dir_path.clone()).unwrap();

let mount_options = vec![
"rbind".to_string(),
"rnosymfollow".to_string(),
"rsuid".to_string(),
];
let mut mount_spec = Mount::default();
mount_spec
.set_destination(mount_dest_path)
.set_typ(None)
.set_source(Some(rnosymfollow_dir_path.clone()))
.set_options(Some(mount_options));
let spec = get_spec(
vec![mount_spec],
vec!["runtimetest".to_string(), "mounts_recursive".to_string()],
);
let result = test_inside_container(spec, &|_| {
let original_file_path = format!("{}/{}", rnosymfollow_dir_path.to_str().unwrap(), "file");
File::create(original_file_path.clone())?;
let link_file_path = format!("{}/{}", rnosymfollow_dir_path.to_str().unwrap(), "link");
println!("original file: {original_file_path:?},link file: {link_file_path:?}");
Command::new("chmod")
.args(["+s", original_file_path.as_str()])
.output()?;
Command::new("chmod")
.args(["+g", original_file_path.as_str()])
.output()?;
symlink(original_file_path, link_file_path)?;
println!("symlink success");
Ok(())
});

fs::remove_dir_all(rnosymfollow_dir_path).unwrap();
result
}

/// this mount test how to work?
/// 1. Create mount_options based on the mount properties of the test
/// 2. Create OCI.Spec content, container one process is runtimetest,(runtimetest is cargo model, file path `tests/rust-integration-tests/runtimetest/`)
Expand All @@ -500,6 +577,7 @@ fn check_recursive_rstrictatime() -> TestResult {
pub fn get_mounts_recursive_test() -> TestGroup {
let rro_test = Test::new("rro_test", Box::new(check_recursive_readonly));
let rnosuid_test = Test::new("rnosuid_test", Box::new(check_recursive_nosuid));
let rsuid_test = Test::new("rsuid_test", Box::new(check_recursive_rsuid));
let rnoexec_test = Test::new("rnoexec_test", Box::new(check_recursive_noexec));
let rnodiratime_test = Test::new("rnodiratime_test", Box::new(check_recursive_rnodiratime));
let rdiratime_test = Test::new("rdiratime_test", Box::new(check_recursive_rdiratime));
Expand All @@ -511,11 +589,13 @@ pub fn get_mounts_recursive_test() -> TestGroup {
let rnorelatime_test = Test::new("rnorelatime_test", Box::new(check_recursive_rnorelatime));
let rnoatime_test = Test::new("rnoatime_test", Box::new(check_recursive_rnoatime));
let rstrictatime_test = Test::new("rstrictatime_test", Box::new(check_recursive_rstrictatime));
let rnosymfollow_test = Test::new("rnosymfollow_test", Box::new(check_recursive_rnosymfollow));

let mut tg = TestGroup::new("mounts_recursive");
tg.add(vec![
Box::new(rro_test),
Box::new(rnosuid_test),
Box::new(rsuid_test),
Box::new(rnoexec_test),
Box::new(rdiratime_test),
Box::new(rnodiratime_test),
Expand All @@ -527,6 +607,7 @@ pub fn get_mounts_recursive_test() -> TestGroup {
Box::new(rnorelatime_test),
Box::new(rnoatime_test),
Box::new(rstrictatime_test),
Box::new(rnosymfollow_test),
]);

tg
Expand Down
14 changes: 14 additions & 0 deletions tests/rust-integration-tests/runtimetest/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,20 @@ pub fn validate_mounts_recursive(spec: &Spec) {
eprintln!("path expected to be rstrictatime, found not rstrictatime, error: {e}");
}
}
"rnosymfollow" => {
if let Err(e) = utils::test_mount_rnosymfollow_option(
mount.destination().to_str().unwrap(),
) {
eprintln!("path expected to be rnosymfollow, found not rnosymfollow, error: {e}");
}
}
"rsuid" => {
if let Err(e) = utils::test_mount_rsuid_option(
mount.destination().to_str().unwrap(),
) {
eprintln!("path expected to be rsuid, found not rsuid, error: {e}");
}
}
_ => {}
}
}
Expand Down
50 changes: 50 additions & 0 deletions tests/rust-integration-tests/runtimetest/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use nix::sys::stat::stat;
use nix::sys::stat::SFlag;
use std::fs;
use std::fs::metadata;
use std::fs::symlink_metadata;
use std::os::unix::prelude::MetadataExt;
use std::path::PathBuf;
use std::process::Command;
Expand Down Expand Up @@ -401,3 +403,51 @@ pub fn test_mount_rstrictatime_option(path: &str) -> Result<(), std::io::Error>
}
Ok(())
}

pub fn test_mount_rnosymfollow_option(path: &str) -> Result<(), std::io::Error> {
let path = format!("{}/{}", path, "link");
// 获取文件元数据
let metadata = match symlink_metadata(path.clone()) {
Ok(metadata) => metadata,
Err(e) => {
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
format!("get file symlink_metadata err {path:?}, {e}"),
));
}
};
// 检查是否可以跟随符号链接
if metadata.file_type().is_symlink() && metadata.mode() & 0o777 == 0o777 {
println!("Symbolic link cannot be followed.");
Ok(())
} else {
println!("Symbolic link can be followed.");
Err(std::io::Error::new(
std::io::ErrorKind::Other,
format!("get file symlink_metadata err {path:?}"),
))
}
}

pub fn test_mount_rsuid_option(path: &str) -> Result<(), std::io::Error> {
let path = PathBuf::from(path).join("file");

// 获取文件元数据
let metadata = match metadata(path.clone()) {
Ok(metadata) => metadata,
Err(e) => {
return Err(std::io::Error::new(std::io::ErrorKind::Other, e));
}
};
// 检查SUID位和SGID位
let suid = metadata.mode() & 0o4000 == 0o4000;
let sgid = metadata.mode() & 0o2000 == 0o2000;
println!("suid: {suid:?},sgid: {sgid:?}");
if suid && sgid {
return Ok(());
}
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
format!("rsuid error {path:?}"),
));
}

0 comments on commit 07c3548

Please sign in to comment.