diff --git a/tests/contest/contest/src/main.rs b/tests/contest/contest/src/main.rs index bb1019ca8..3a1a7a1d8 100644 --- a/tests/contest/contest/src/main.rs +++ b/tests/contest/contest/src/main.rs @@ -22,6 +22,7 @@ use crate::tests::mounts_recursive::get_mounts_recursive_test; use crate::tests::no_pivot::get_no_pivot_test; use crate::tests::pidfile::get_pidfile_test; use crate::tests::process::get_process_test; +use crate::tests::process_capabilities_fail::get_process_capabilities_fail_test; use crate::tests::process_oom_score_adj::get_process_oom_score_adj_test; use crate::tests::process_rlimits::get_process_rlimits_test; use crate::tests::process_user::get_process_user_test; @@ -125,6 +126,7 @@ fn main() -> Result<()> { let process_rlimtis = get_process_rlimits_test(); let no_pivot = get_no_pivot_test(); let process_oom_score_adj = get_process_oom_score_adj_test(); + let process_capabilities_fail = get_process_capabilities_fail_test(); tm.add_test_group(Box::new(cl)); tm.add_test_group(Box::new(cc)); @@ -154,6 +156,7 @@ fn main() -> Result<()> { tm.add_test_group(Box::new(process_rlimtis)); tm.add_test_group(Box::new(no_pivot)); tm.add_test_group(Box::new(process_oom_score_adj)); + tm.add_test_group(Box::new(process_capabilities_fail)); tm.add_test_group(Box::new(io_priority_test)); tm.add_cleanup(Box::new(cgroups::cleanup_v1)); diff --git a/tests/contest/contest/src/tests/mod.rs b/tests/contest/contest/src/tests/mod.rs index 6e8e39be8..d7ae631fe 100644 --- a/tests/contest/contest/src/tests/mod.rs +++ b/tests/contest/contest/src/tests/mod.rs @@ -12,6 +12,7 @@ pub mod mounts_recursive; pub mod no_pivot; pub mod pidfile; pub mod process; +pub mod process_capabilities_fail; pub mod process_oom_score_adj; pub mod process_rlimits; pub mod process_user; diff --git a/tests/contest/contest/src/tests/process_capabilities_fail/mod.rs b/tests/contest/contest/src/tests/process_capabilities_fail/mod.rs new file mode 100644 index 000000000..37bf429b5 --- /dev/null +++ b/tests/contest/contest/src/tests/process_capabilities_fail/mod.rs @@ -0,0 +1,2 @@ +mod process_capabilities_fail_test; +pub use process_capabilities_fail_test::get_process_capabilities_fail_test; diff --git a/tests/contest/contest/src/tests/process_capabilities_fail/process_capabilities_fail_test.rs b/tests/contest/contest/src/tests/process_capabilities_fail/process_capabilities_fail_test.rs new file mode 100644 index 000000000..c4eac8386 --- /dev/null +++ b/tests/contest/contest/src/tests/process_capabilities_fail/process_capabilities_fail_test.rs @@ -0,0 +1,79 @@ +use std::{collections::HashSet, fs, fs::OpenOptions, io::Write}; + +use anyhow::{anyhow, Context, Ok, Result}; +use oci_spec::runtime::{Capability, LinuxCapabilitiesBuilder, ProcessBuilder, Spec, SpecBuilder}; +use test_framework::{test_result, Test, TestGroup, TestResult}; + +use serde_json::Value; + +use crate::utils::{test_inside_container, test_utils::CreateOptions}; + +fn create_spec() -> Result { + let linux_capability = LinuxCapabilitiesBuilder::default() + .bounding(HashSet::from([Capability::Syslog])) + .build()?; + + let process = ProcessBuilder::default() + .args(vec![ + "runtimetest".to_string(), + "process_capabilities_fail".to_string(), + ]) + .capabilities(linux_capability) + .build() + .expect("error in creating process config"); + + let spec = SpecBuilder::default() + .process(process) + .build() + .context("failed to build spec")?; + + Ok(spec) +} + +fn process_capabilities_fail_test() -> TestResult { + let spec = test_result!(create_spec()); + let result = test_inside_container(spec, &CreateOptions::default(), &|bundle| { + let spec_path = bundle.join("../config.json"); + let spec_str = fs::read_to_string(spec_path.clone()).unwrap(); + + let mut spec_json: Value = serde_json::from_str(&spec_str)?; + + if let Some(bounding) = spec_json.pointer_mut("/process/capabilities/bounding") { + if let Some(bounding_array) = bounding.as_array_mut() { + for capanility in bounding_array.iter_mut() { + if capanility == "CAP_SYSLOG" { + *capanility = Value::String("TEST_CAP".to_string()); + } + } + } + } + + let updated_spec_str = serde_json::to_string_pretty(&spec_json)?; + + let mut file = OpenOptions::new() + .write(true) + .truncate(true) + .open(spec_path)?; + file.write_all(updated_spec_str.as_bytes())?; + + Ok(()) + }); + match result { + TestResult::Failed(_e) => TestResult::Passed, + TestResult::Skipped => TestResult::Failed(anyhow!("test was skipped unexpectedly.")), + TestResult::Passed => { + TestResult::Failed(anyhow!("container creation succeeded unexpectedly.")) + } + } +} + +pub fn get_process_capabilities_fail_test() -> TestGroup { + let mut process_capabilities_fail_test_group = TestGroup::new("process_capabilities_fail"); + let test = Test::new( + "process_capabilities_fail_test", + Box::new(process_capabilities_fail_test), + ); + process_capabilities_fail_test_group.add(vec![Box::new(test)]); + + process_capabilities_fail_test_group +} diff --git a/tests/contest/contest/src/utils/test_utils.rs b/tests/contest/contest/src/utils/test_utils.rs index 0964a9a04..4a980c2cf 100644 --- a/tests/contest/contest/src/utils/test_utils.rs +++ b/tests/contest/contest/src/utils/test_utils.rs @@ -201,7 +201,10 @@ pub fn test_inside_container( .join("runtimetest"), ) .unwrap(); - let create_process = create_container(&id_str, &bundle, options).unwrap(); + let create_process = match create_container(&id_str, &bundle, options) { + Ok(p) => p, + Err(e) => return TestResult::Failed(anyhow!("container create failed : {:?}", e)), + }; // here we do not wait for the process by calling wait() as in the test_outside_container // function because we need the output of the runtimetest. If we call wait, it will return // and we won't have an easy way of getting the stdio of the runtimetest.