From 1cbfba4aa6d13ac2af7fa65b9ec000a7e64878a1 Mon Sep 17 00:00:00 2001 From: sat0ken <15720506+sat0ken@users.noreply.github.com> Date: Thu, 21 Nov 2024 20:28:21 +0900 Subject: [PATCH 1/6] add test code linux_cgroups_devices Signed-off-by: sat0ken <15720506+sat0ken@users.noreply.github.com> --- tests/contest/contest/src/main.rs | 2 + .../contest/src/tests/cgroups/devices.rs | 83 +++++++++++++++++++ .../contest/contest/src/tests/cgroups/mod.rs | 1 + 3 files changed, 86 insertions(+) create mode 100644 tests/contest/contest/src/tests/cgroups/devices.rs diff --git a/tests/contest/contest/src/main.rs b/tests/contest/contest/src/main.rs index d4d2dbac2..336f62aa7 100644 --- a/tests/contest/contest/src/main.rs +++ b/tests/contest/contest/src/main.rs @@ -103,6 +103,7 @@ fn main() -> Result<()> { let cgroup_v1_pids = cgroups::pids::get_test_group(); let cgroup_v1_cpu = cgroups::cpu::v1::get_test_group(); let cgroup_v2_cpu = cgroups::cpu::v2::get_test_group(); + let cgroup_v1_device = cgroups::devices::get_test_group(); let cgroup_v1_memory = cgroups::memory::get_test_group(); let cgroup_v1_network = cgroups::network::get_test_group(); let cgroup_v1_blkio = cgroups::blkio::get_test_group(); @@ -131,6 +132,7 @@ fn main() -> Result<()> { tm.add_test_group(Box::new(cgroup_v1_pids)); tm.add_test_group(Box::new(cgroup_v1_cpu)); tm.add_test_group(Box::new(cgroup_v2_cpu)); + tm.add_test_group(Box::new(cgroup_v1_device)); tm.add_test_group(Box::new(cgroup_v1_memory)); tm.add_test_group(Box::new(cgroup_v1_network)); tm.add_test_group(Box::new(cgroup_v1_blkio)); diff --git a/tests/contest/contest/src/tests/cgroups/devices.rs b/tests/contest/contest/src/tests/cgroups/devices.rs new file mode 100644 index 000000000..dd09f534f --- /dev/null +++ b/tests/contest/contest/src/tests/cgroups/devices.rs @@ -0,0 +1,83 @@ +use std::path::Path; + +use crate::utils::test_outside_container; +use crate::utils::test_utils::check_container_created; +use anyhow::Context; +use oci_spec::runtime::{ + LinuxBuilder, LinuxDeviceCgroup, LinuxDeviceCgroupBuilder, LinuxDeviceType, + LinuxResourcesBuilder, Spec, SpecBuilder, +}; +use test_framework::{test_result, ConditionalTest, TestGroup, TestResult}; + +fn can_run() -> bool { + Path::new("/sys/fs/cgroup/devices").exists() +} + +fn linux_device_build( + allow: bool, + dev_type: LinuxDeviceType, + major: i64, + minor: i64, + access: String, +) -> LinuxDeviceCgroup { + LinuxDeviceCgroupBuilder::default() + .access(allow.to_string()) + .typ(dev_type) + .major(major) + .minor(minor) + .access(access) + .build() + .unwrap() +} + +fn create_spec(cgroup_name: &str, devices: Vec) -> anyhow::Result { + let spec = SpecBuilder::default() + .linux( + LinuxBuilder::default() + .cgroups_path(Path::new("/runtime-test").join(cgroup_name)) + .resources( + LinuxResourcesBuilder::default() + .devices(devices) + .build() + .context("failed to build resource spec")?, + ) + .build() + .context("failed to build linux spec")?, + ) + .build() + .context("failed to build spec")?; + + Ok(spec) +} + +fn test_devices_cgroups() -> TestResult { + let cgroup_name = "test_devices_cgroups"; + let linux_devices = vec![ + linux_device_build(true, LinuxDeviceType::C, 10, 229, "rwm".to_string()), + linux_device_build(true, LinuxDeviceType::B, 8, 20, "rw".to_string()), + linux_device_build(true, LinuxDeviceType::B, 10, 200, "r".to_string()), + ]; + let spec = test_result!(create_spec(cgroup_name, linux_devices)); + + let test_result = test_outside_container(spec, &|data| { + test_result!(check_container_created(&data)); + TestResult::Passed + }); + if let TestResult::Failed(_) = test_result { + return test_result; + } + test_result +} + +pub fn get_test_group() -> TestGroup { + let mut test_group = TestGroup::new("cgroup_v1_devices"); + let linux_cgroups_devices = ConditionalTest::new( + "test_linux_cgroups_devices", + Box::new(can_run), + Box::new(crate::tests::cgroups::devices::test_devices_cgroups), + ); + + test_group.add(vec![Box::new(linux_cgroups_devices)]); + + test_group +} diff --git a/tests/contest/contest/src/tests/cgroups/mod.rs b/tests/contest/contest/src/tests/cgroups/mod.rs index 51f467d5c..cc9ee06bd 100644 --- a/tests/contest/contest/src/tests/cgroups/mod.rs +++ b/tests/contest/contest/src/tests/cgroups/mod.rs @@ -6,6 +6,7 @@ use anyhow::{Context, Result}; use procfs::process::Process; pub mod blkio; pub mod cpu; +pub mod devices; pub mod memory; pub mod network; pub mod pids; From f19119dcd86ac8d1cf389eb1707d5f7cf0f69bdf Mon Sep 17 00:00:00 2001 From: sat0ken <15720506+sat0ken@users.noreply.github.com> Date: Fri, 22 Nov 2024 07:51:43 +0900 Subject: [PATCH 2/6] fix format err Signed-off-by: sat0ken <15720506+sat0ken@users.noreply.github.com> --- tests/contest/contest/src/tests/cgroups/devices.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/contest/contest/src/tests/cgroups/devices.rs b/tests/contest/contest/src/tests/cgroups/devices.rs index dd09f534f..6f224579c 100644 --- a/tests/contest/contest/src/tests/cgroups/devices.rs +++ b/tests/contest/contest/src/tests/cgroups/devices.rs @@ -1,7 +1,5 @@ use std::path::Path; -use crate::utils::test_outside_container; -use crate::utils::test_utils::check_container_created; use anyhow::Context; use oci_spec::runtime::{ LinuxBuilder, LinuxDeviceCgroup, LinuxDeviceCgroupBuilder, LinuxDeviceType, @@ -9,6 +7,9 @@ use oci_spec::runtime::{ }; use test_framework::{test_result, ConditionalTest, TestGroup, TestResult}; +use crate::utils::test_outside_container; +use crate::utils::test_utils::check_container_created; + fn can_run() -> bool { Path::new("/sys/fs/cgroup/devices").exists() } From 0ea31ff49b399e79ac9165f159968b95c75e7f1d Mon Sep 17 00:00:00 2001 From: sat0ken <15720506+sat0ken@users.noreply.github.com> Date: Thu, 16 Jan 2025 20:27:53 +0900 Subject: [PATCH 3/6] fix linux_device_build func Signed-off-by: sat0ken <15720506+sat0ken@users.noreply.github.com> --- tests/contest/contest/src/tests/cgroups/devices.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/contest/contest/src/tests/cgroups/devices.rs b/tests/contest/contest/src/tests/cgroups/devices.rs index 6f224579c..b7869ba0e 100644 --- a/tests/contest/contest/src/tests/cgroups/devices.rs +++ b/tests/contest/contest/src/tests/cgroups/devices.rs @@ -15,14 +15,13 @@ fn can_run() -> bool { } fn linux_device_build( - allow: bool, dev_type: LinuxDeviceType, major: i64, minor: i64, access: String, ) -> LinuxDeviceCgroup { LinuxDeviceCgroupBuilder::default() - .access(allow.to_string()) + .allow(true) .typ(dev_type) .major(major) .minor(minor) @@ -54,9 +53,9 @@ fn create_spec(cgroup_name: &str, devices: Vec) -> anyhow::Re fn test_devices_cgroups() -> TestResult { let cgroup_name = "test_devices_cgroups"; let linux_devices = vec![ - linux_device_build(true, LinuxDeviceType::C, 10, 229, "rwm".to_string()), - linux_device_build(true, LinuxDeviceType::B, 8, 20, "rw".to_string()), - linux_device_build(true, LinuxDeviceType::B, 10, 200, "r".to_string()), + linux_device_build(LinuxDeviceType::C, 10, 229, "rwm".to_string()), + linux_device_build(LinuxDeviceType::B, 8, 20, "rw".to_string()), + linux_device_build(LinuxDeviceType::B, 10, 200, "r".to_string()), ]; let spec = test_result!(create_spec(cgroup_name, linux_devices)); From dc5a1c16b0bb7db36df363c2c8a31fce2dca1bc5 Mon Sep 17 00:00:00 2001 From: sat0ken <15720506+sat0ken@users.noreply.github.com> Date: Sat, 18 Jan 2025 22:04:55 +0900 Subject: [PATCH 4/6] read cgroup devices.list and check spec file Signed-off-by: sat0ken <15720506+sat0ken@users.noreply.github.com> --- .../contest/src/tests/cgroups/devices.rs | 99 +++++++++++++++++-- 1 file changed, 89 insertions(+), 10 deletions(-) diff --git a/tests/contest/contest/src/tests/cgroups/devices.rs b/tests/contest/contest/src/tests/cgroups/devices.rs index b7869ba0e..6755fb74a 100644 --- a/tests/contest/contest/src/tests/cgroups/devices.rs +++ b/tests/contest/contest/src/tests/cgroups/devices.rs @@ -1,10 +1,13 @@ -use std::path::Path; +use std::fs::File; +use std::io::{BufRead, BufReader}; +use std::path::{Path, PathBuf}; -use anyhow::Context; +use anyhow::{bail, Context, Result}; use oci_spec::runtime::{ LinuxBuilder, LinuxDeviceCgroup, LinuxDeviceCgroupBuilder, LinuxDeviceType, LinuxResourcesBuilder, Spec, SpecBuilder, }; +use contest::utils::test_utils::CGROUP_ROOT; use test_framework::{test_result, ConditionalTest, TestGroup, TestResult}; use crate::utils::test_outside_container; @@ -30,7 +33,7 @@ fn linux_device_build( .unwrap() } -fn create_spec(cgroup_name: &str, devices: Vec) -> anyhow::Result { +fn create_spec(cgroup_name: &str, devices: Vec) -> Result { let spec = SpecBuilder::default() .linux( LinuxBuilder::default() @@ -50,6 +53,85 @@ fn create_spec(cgroup_name: &str, devices: Vec) -> anyhow::Re Ok(spec) } +fn get_allow_linux_devices(path: &Path) -> Result> { + let file = File::open(path).unwrap()?; + let reader = BufReader::new(file); + let mut devices :Vec = vec![]; + + for line in reader.lines() { + let line = line?; + let parts: Vec<&str> = line.split_whitespace().collect(); + if parts.len() == 3 { + let device_type = match parts[0] { + "b" => LinuxDeviceType::B, + "c" => LinuxDeviceType::C, + "*" => LinuxDeviceType::A, + _ => continue, + }; + // read major, minor number + let major_minor: Vec<&str> = parts[1].split(':').collect(); + if major_minor.len() != 2 { + // ignore invalid format + continue; + } + let major = if major_minor[0] == "*" { + None + } else { + major_minor[0].parse::().ok() + }; + let minor = if major_minor[1] == "*" { + None + } else { + major_minor[1].parse::().ok() + }; + // read access string + let access = parts[2].to_string(); + devices.push(linux_device_build( + device_type, major, minor, access, + )) + } + } + + Ok(devices); +} + +fn validate_linux_devices(cgroup_name: &str, spec: &Spec) -> Result<()> { + let cgroup_path = PathBuf::from(CGROUP_ROOT) + .join("devices") + .join("runtime-test") + .join(cgroup_name) + .join("devices.list"); + let linux_devices = get_allow_linux_devices(&cgroup_path)?; + + let resources = spec.linux().as_ref().unwrap().resources().as_ref().unwrap(); + let spec_linux_devices = resources.devices().as_ref().unwrap(); + + for spec_linux_device in spec_linux_devices { + if spec_linux_device.allow() { + let mut found = false; + for linux_device in linux_devices.clone() { + if linux_device.typ() == spec_linux_device.typ() && + linux_device.major() == spec_linux_device.major() && + linux_device.minor() == spec_linux_device.minor() && + linux_device.access() == spec_linux_device.access() { + found = true; + } + } + if !found { + bail!( + "allow linux device {}:{}:{}:{} not found, exists in spec", + spec_linux_device.typ(), + spec_linux_device.major(), + spec_linux_device.minor(), + spec_linux_device.access() + ); + } + } + } + + Ok(()) +} + fn test_devices_cgroups() -> TestResult { let cgroup_name = "test_devices_cgroups"; let linux_devices = vec![ @@ -59,14 +141,11 @@ fn test_devices_cgroups() -> TestResult { ]; let spec = test_result!(create_spec(cgroup_name, linux_devices)); - let test_result = test_outside_container(spec, &|data| { + test_outside_container(spec.clone(), &|data| { test_result!(check_container_created(&data)); + test_result!(validate_linux_devices(&cgroup_name, &spec)); TestResult::Passed - }); - if let TestResult::Failed(_) = test_result { - return test_result; - } - test_result + }) } pub fn get_test_group() -> TestGroup { @@ -74,7 +153,7 @@ pub fn get_test_group() -> TestGroup { let linux_cgroups_devices = ConditionalTest::new( "test_linux_cgroups_devices", Box::new(can_run), - Box::new(crate::tests::cgroups::devices::test_devices_cgroups), + Box::new(test_devices_cgroups), ); test_group.add(vec![Box::new(linux_cgroups_devices)]); From 22a5225cc6a7925ddc6123a5d94dc693778927a6 Mon Sep 17 00:00:00 2001 From: sat0ken <15720506+sat0ken@users.noreply.github.com> Date: Sat, 18 Jan 2025 22:21:06 +0900 Subject: [PATCH 5/6] fix format err Signed-off-by: sat0ken <15720506+sat0ken@users.noreply.github.com> --- .../contest/src/tests/cgroups/devices.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/tests/contest/contest/src/tests/cgroups/devices.rs b/tests/contest/contest/src/tests/cgroups/devices.rs index 6755fb74a..917b281dc 100644 --- a/tests/contest/contest/src/tests/cgroups/devices.rs +++ b/tests/contest/contest/src/tests/cgroups/devices.rs @@ -3,11 +3,11 @@ use std::io::{BufRead, BufReader}; use std::path::{Path, PathBuf}; use anyhow::{bail, Context, Result}; +use contest::utils::test_utils::CGROUP_ROOT; use oci_spec::runtime::{ LinuxBuilder, LinuxDeviceCgroup, LinuxDeviceCgroupBuilder, LinuxDeviceType, LinuxResourcesBuilder, Spec, SpecBuilder, }; -use contest::utils::test_utils::CGROUP_ROOT; use test_framework::{test_result, ConditionalTest, TestGroup, TestResult}; use crate::utils::test_outside_container; @@ -56,7 +56,7 @@ fn create_spec(cgroup_name: &str, devices: Vec) -> Result Result> { let file = File::open(path).unwrap()?; let reader = BufReader::new(file); - let mut devices :Vec = vec![]; + let mut devices: Vec = vec![]; for line in reader.lines() { let line = line?; @@ -86,9 +86,7 @@ fn get_allow_linux_devices(path: &Path) -> Result> { }; // read access string let access = parts[2].to_string(); - devices.push(linux_device_build( - device_type, major, minor, access, - )) + devices.push(linux_device_build(device_type, major, minor, access)) } } @@ -110,11 +108,12 @@ fn validate_linux_devices(cgroup_name: &str, spec: &Spec) -> Result<()> { if spec_linux_device.allow() { let mut found = false; for linux_device in linux_devices.clone() { - if linux_device.typ() == spec_linux_device.typ() && - linux_device.major() == spec_linux_device.major() && - linux_device.minor() == spec_linux_device.minor() && - linux_device.access() == spec_linux_device.access() { - found = true; + if linux_device.typ() == spec_linux_device.typ() + && linux_device.major() == spec_linux_device.major() + && linux_device.minor() == spec_linux_device.minor() + && linux_device.access() == spec_linux_device.access() + { + found = true; } } if !found { From 4bcf5f69c0026e46426b5b82fcad19c1589535f2 Mon Sep 17 00:00:00 2001 From: sat0ken <15720506+sat0ken@users.noreply.github.com> Date: Sun, 19 Jan 2025 10:34:15 +0900 Subject: [PATCH 6/6] fix format err Signed-off-by: sat0ken <15720506+sat0ken@users.noreply.github.com> --- .../contest/src/tests/cgroups/devices.rs | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/tests/contest/contest/src/tests/cgroups/devices.rs b/tests/contest/contest/src/tests/cgroups/devices.rs index 917b281dc..6274d0fd4 100644 --- a/tests/contest/contest/src/tests/cgroups/devices.rs +++ b/tests/contest/contest/src/tests/cgroups/devices.rs @@ -2,8 +2,7 @@ use std::fs::File; use std::io::{BufRead, BufReader}; use std::path::{Path, PathBuf}; -use anyhow::{bail, Context, Result}; -use contest::utils::test_utils::CGROUP_ROOT; +use anyhow::{bail, Context, Error, Result}; use oci_spec::runtime::{ LinuxBuilder, LinuxDeviceCgroup, LinuxDeviceCgroupBuilder, LinuxDeviceType, LinuxResourcesBuilder, Spec, SpecBuilder, @@ -11,7 +10,7 @@ use oci_spec::runtime::{ use test_framework::{test_result, ConditionalTest, TestGroup, TestResult}; use crate::utils::test_outside_container; -use crate::utils::test_utils::check_container_created; +use crate::utils::test_utils::{check_container_created, CGROUP_ROOT}; fn can_run() -> bool { Path::new("/sys/fs/cgroup/devices").exists() @@ -53,8 +52,8 @@ fn create_spec(cgroup_name: &str, devices: Vec) -> Result Result> { - let file = File::open(path).unwrap()?; +fn get_allow_linux_devices(path: &Path) -> Result, Error> { + let file = File::open(path)?; let reader = BufReader::new(file); let mut devices: Vec = vec![]; @@ -86,11 +85,16 @@ fn get_allow_linux_devices(path: &Path) -> Result> { }; // read access string let access = parts[2].to_string(); - devices.push(linux_device_build(device_type, major, minor, access)) + devices.push(linux_device_build( + device_type, + major.unwrap(), + minor.unwrap(), + access, + )) } } - Ok(devices); + Ok(devices) } fn validate_linux_devices(cgroup_name: &str, spec: &Spec) -> Result<()> { @@ -119,10 +123,10 @@ fn validate_linux_devices(cgroup_name: &str, spec: &Spec) -> Result<()> { if !found { bail!( "allow linux device {}:{}:{}:{} not found, exists in spec", - spec_linux_device.typ(), - spec_linux_device.major(), - spec_linux_device.minor(), - spec_linux_device.access() + spec_linux_device.typ().unwrap().as_str(), + spec_linux_device.major().unwrap(), + spec_linux_device.minor().unwrap(), + spec_linux_device.access().as_ref().unwrap() ); } } @@ -142,7 +146,7 @@ fn test_devices_cgroups() -> TestResult { test_outside_container(spec.clone(), &|data| { test_result!(check_container_created(&data)); - test_result!(validate_linux_devices(&cgroup_name, &spec)); + test_result!(validate_linux_devices(cgroup_name, &spec)); TestResult::Passed }) }