From 85f9094f17c4dabd5a3179be54f67c0abe551467 Mon Sep 17 00:00:00 2001 From: Yushuo Date: Sun, 4 Dec 2022 16:24:49 +0800 Subject: [PATCH] agent: refactor guest hooks We have to execute some hooks both in host and guest. And in /libs/kata-sys-util/src/hooks.rs, the coomon operations are implemented. In this commit, we are going to refactor the code of guest hooks using code in /libs/kata-sys-util/src/hooks.rs. At the same time, we move function valid_env to kata-sys-util to make it usable by both agent and runtime. Fixes: #5857 Signed-off-by: Yushuo --- src/agent/Cargo.lock | 1 + src/agent/rustjail/Cargo.toml | 1 + src/agent/rustjail/src/container.rs | 342 ++----------------- src/libs/Cargo.lock | 8 + src/libs/kata-sys-util/src/hooks.rs | 6 +- src/libs/kata-sys-util/src/validate.rs | 66 ++++ src/tools/runk/Cargo.lock | 171 +++++++++- src/tools/runk/libcontainer/Cargo.toml | 1 + src/tools/runk/libcontainer/src/container.rs | 18 +- 9 files changed, 281 insertions(+), 333 deletions(-) diff --git a/src/agent/Cargo.lock b/src/agent/Cargo.lock index 4b351c5c6def..3a251a2bd14d 100644 --- a/src/agent/Cargo.lock +++ b/src/agent/Cargo.lock @@ -1684,6 +1684,7 @@ dependencies = [ "cgroups-rs", "futures", "inotify", + "kata-sys-util", "lazy_static", "libc", "libseccomp", diff --git a/src/agent/rustjail/Cargo.toml b/src/agent/rustjail/Cargo.toml index 031175e8670c..8a0c413d25df 100644 --- a/src/agent/rustjail/Cargo.toml +++ b/src/agent/rustjail/Cargo.toml @@ -11,6 +11,7 @@ serde_json = "1.0.39" serde_derive = "1.0.91" oci = { path = "../../libs/oci" } protocols = { path ="../../libs/protocols" } +kata-sys-util = { path = "../../libs/kata-sys-util" } caps = "0.5.0" nix = "0.24.2" scopeguard = "1.0.0" diff --git a/src/agent/rustjail/src/container.rs b/src/agent/rustjail/src/container.rs index de92adf4ceac..c869d274e7f0 100644 --- a/src/agent/rustjail/src/container.rs +++ b/src/agent/rustjail/src/container.rs @@ -6,7 +6,7 @@ use anyhow::{anyhow, Context, Result}; use libc::pid_t; use oci::{ContainerState, LinuxDevice, LinuxIdMapping}; -use oci::{Hook, Linux, LinuxNamespace, LinuxResources, Spec}; +use oci::{Linux, LinuxNamespace, LinuxResources, Spec}; use std::clone::Clone; use std::ffi::CString; use std::fmt::Display; @@ -66,6 +66,9 @@ use rlimit::{setrlimit, Resource, Rlim}; use tokio::io::AsyncBufReadExt; use tokio::sync::Mutex; +use kata_sys_util::hooks::HookStates; +use kata_sys_util::validate::valid_env; + pub const EXEC_FIFO_FILENAME: &str = "exec.fifo"; const INIT: &str = "INIT"; @@ -1099,12 +1102,14 @@ impl BaseContainer for LinuxContainer { } } - if spec.hooks.is_some() { - info!(self.logger, "poststop"); - let hooks = spec.hooks.as_ref().unwrap(); - for h in hooks.poststop.iter() { - execute_hook(&self.logger, h, &st).await?; - } + // guest Poststop hook + // * should be executed after the container is deleted but before the delete operation returns + // * the executable file is in agent namespace + // * should also be executed in agent namespace. + if let Some(hooks) = spec.hooks.as_ref() { + info!(self.logger, "guest Poststop hook"); + let mut hook_states = HookStates::new(); + hook_states.execute_hooks(&hooks.poststop, Some(st))?; } self.status.transition(ContainerState::Stopped); @@ -1150,16 +1155,14 @@ impl BaseContainer for LinuxContainer { .ok_or_else(|| anyhow!("OCI spec was not found"))?; let st = self.oci_state()?; - // run poststart hook - if spec.hooks.is_some() { - info!(self.logger, "poststart hook"); - let hooks = spec - .hooks - .as_ref() - .ok_or_else(|| anyhow!("OCI hooks were not found"))?; - for h in hooks.poststart.iter() { - execute_hook(&self.logger, h, &st).await?; - } + // guest Poststart hook + // * should be executed after the container is started but before the delete operation returns + // * the executable file is in agent namespace + // * should also be executed in agent namespace. + if let Some(hooks) = spec.hooks.as_ref() { + info!(self.logger, "guest Poststart hook"); + let mut hook_states = HookStates::new(); + hook_states.execute_hooks(&hooks.poststart, Some(st))?; } unistd::close(fd)?; @@ -1380,13 +1383,14 @@ async fn join_namespaces( info!(logger, "get ready to run prestart hook!"); - // run prestart hook - if spec.hooks.is_some() { - info!(logger, "prestart hook"); - let hooks = spec.hooks.as_ref().unwrap(); - for h in hooks.prestart.iter() { - execute_hook(&logger, h, st).await?; - } + // guest Prestart hook + // * should be executed during the start operation, and before the container command is executed + // * the executable file is in agent namespace + // * should also be executed in agent namespace. + if let Some(hooks) = spec.hooks.as_ref() { + info!(logger, "guest Prestart hook"); + let mut hook_states = HookStates::new(); + hook_states.execute_hooks(&hooks.prestart, Some(st.clone()))?; } // notify child run prestart hooks completed @@ -1566,143 +1570,6 @@ fn set_sysctls(sysctls: &HashMap) -> Result<()> { Ok(()) } -use std::process::Stdio; -use std::time::Duration; -use tokio::io::{AsyncReadExt, AsyncWriteExt}; - -pub async fn execute_hook(logger: &Logger, h: &Hook, st: &OCIState) -> Result<()> { - let logger = logger.new(o!("action" => "execute-hook")); - - let binary = PathBuf::from(h.path.as_str()); - let path = binary.canonicalize()?; - if !path.exists() { - return Err(anyhow!("Path {:?} does not exist", path)); - } - - let mut args = h.args.clone(); - // the hook.args[0] is the hook binary name which shouldn't be included - // in the Command.args - if args.len() > 1 { - args.remove(0); - } - - // all invalid envs will be omitted, only valid envs will be passed to hook. - let env: HashMap<&str, &str> = h.env.iter().filter_map(|e| valid_env(e)).collect(); - - // Avoid the exit signal to be reaped by the global reaper. - let _wait_locker = WAIT_PID_LOCKER.lock().await; - let mut child = tokio::process::Command::new(path) - .args(args.iter()) - .envs(env.iter()) - .kill_on_drop(true) - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn()?; - - // default timeout 10s - let mut timeout: u64 = 10; - - // if timeout is set if hook, then use the specified value - if let Some(t) = h.timeout { - if t > 0 { - timeout = t as u64; - } - } - - let state = serde_json::to_string(st)?; - let path = h.path.clone(); - - let join_handle = tokio::spawn(async move { - if let Some(mut stdin) = child.stdin.take() { - match stdin.write_all(state.as_bytes()).await { - Ok(_) => {} - Err(e) => { - info!(logger, "write to child stdin failed: {:?}", e); - } - } - } - - // read something from stdout and stderr for debug - if let Some(stdout) = child.stdout.as_mut() { - let mut out = String::new(); - match stdout.read_to_string(&mut out).await { - Ok(_) => { - info!(logger, "child stdout: {}", out.as_str()); - } - Err(e) => { - info!(logger, "read from child stdout failed: {:?}", e); - } - } - } - - let mut err = String::new(); - if let Some(stderr) = child.stderr.as_mut() { - match stderr.read_to_string(&mut err).await { - Ok(_) => { - info!(logger, "child stderr: {}", err.as_str()); - } - Err(e) => { - info!(logger, "read from child stderr failed: {:?}", e); - } - } - } - - match child.wait().await { - Ok(exit) => { - let code = exit - .code() - .ok_or_else(|| anyhow!("hook exit status has no status code"))?; - - if code != 0 { - error!( - logger, - "hook {} exit status is {}, error message is {}", &path, code, err - ); - return Err(anyhow!(nix::Error::UnknownErrno)); - } - - debug!(logger, "hook {} exit status is 0", &path); - Ok(()) - } - Err(e) => Err(anyhow!( - "wait child error: {} {}", - e, - e.raw_os_error().unwrap() - )), - } - }); - - match tokio::time::timeout(Duration::new(timeout, 0), join_handle).await { - Ok(r) => r.unwrap(), - Err(_) => Err(anyhow!(nix::Error::ETIMEDOUT)), - } -} - -// valid environment variables according to https://doc.rust-lang.org/std/env/fn.set_var.html#panics -fn valid_env(e: &str) -> Option<(&str, &str)> { - // wherther key or value will contain NULL char. - if e.as_bytes().contains(&b'\0') { - return None; - } - - let v: Vec<&str> = e.splitn(2, '=').collect(); - - // key can't hold an `equal` sign, but value can - if v.len() != 2 { - return None; - } - - let (key, value) = (v[0].trim(), v[1].trim()); - - // key can't be empty - if key.is_empty() { - return None; - } - - Some((key, value)) -} - #[cfg(test)] mod tests { use super::*; @@ -1713,7 +1580,6 @@ mod tests { use std::os::unix::io::AsRawFd; use tempfile::tempdir; use test_utils::skip_if_not_root; - use tokio::process::Command; macro_rules! sl { () => { @@ -1721,113 +1587,6 @@ mod tests { }; } - async fn which(cmd: &str) -> String { - let output: std::process::Output = Command::new("which") - .arg(cmd) - .output() - .await - .expect("which command failed to run"); - - match String::from_utf8(output.stdout) { - Ok(v) => v.trim_end_matches('\n').to_string(), - Err(e) => panic!("Invalid UTF-8 sequence: {}", e), - } - } - - #[tokio::test] - async fn test_execute_hook() { - let temp_file = "/tmp/test_execute_hook"; - - let touch = which("touch").await; - - defer!(fs::remove_file(temp_file).unwrap();); - let invalid_str = vec![97, b'\0', 98]; - let invalid_string = std::str::from_utf8(&invalid_str).unwrap(); - let invalid_env = format!("{}=value", invalid_string); - - execute_hook( - &slog_scope::logger(), - &Hook { - path: touch, - args: vec!["touch".to_string(), temp_file.to_string()], - env: vec![invalid_env], - timeout: Some(10), - }, - &OCIState { - version: "1.2.3".to_string(), - id: "321".to_string(), - status: ContainerState::Running, - pid: 2, - bundle: "".to_string(), - annotations: Default::default(), - }, - ) - .await - .unwrap(); - - assert_eq!(Path::new(&temp_file).exists(), true); - } - - #[tokio::test] - async fn test_execute_hook_with_error() { - let ls = which("ls").await; - - let res = execute_hook( - &slog_scope::logger(), - &Hook { - path: ls, - args: vec!["ls".to_string(), "/tmp/not-exist".to_string()], - env: vec![], - timeout: None, - }, - &OCIState { - version: "1.2.3".to_string(), - id: "321".to_string(), - status: ContainerState::Running, - pid: 2, - bundle: "".to_string(), - annotations: Default::default(), - }, - ) - .await; - - let expected_err = nix::Error::UnknownErrno; - assert_eq!( - res.unwrap_err().downcast::().unwrap(), - expected_err - ); - } - - #[tokio::test] - async fn test_execute_hook_with_timeout() { - let sleep = which("sleep").await; - - let res = execute_hook( - &slog_scope::logger(), - &Hook { - path: sleep, - args: vec!["sleep".to_string(), "2".to_string()], - env: vec![], - timeout: Some(1), - }, - &OCIState { - version: "1.2.3".to_string(), - id: "321".to_string(), - status: ContainerState::Running, - pid: 2, - bundle: "".to_string(), - annotations: Default::default(), - }, - ) - .await; - - let expected_err = nix::Error::ETIMEDOUT; - assert_eq!( - res.unwrap_err().downcast::().unwrap(), - expected_err - ); - } - #[test] fn test_status_transtition() { let mut status = ContainerStatus::new(); @@ -2167,49 +1926,4 @@ mod tests { let ret = do_init_child(std::io::stdin().as_raw_fd()); assert!(ret.is_err(), "Expecting Err, Got {:?}", ret); } - - #[test] - fn test_valid_env() { - let env = valid_env("a=b=c"); - assert_eq!(Some(("a", "b=c")), env); - - let env = valid_env("a=b"); - assert_eq!(Some(("a", "b")), env); - let env = valid_env("a =b"); - assert_eq!(Some(("a", "b")), env); - - let env = valid_env(" a =b"); - assert_eq!(Some(("a", "b")), env); - - let env = valid_env("a= b"); - assert_eq!(Some(("a", "b")), env); - - let env = valid_env("a=b "); - assert_eq!(Some(("a", "b")), env); - let env = valid_env("a=b c "); - assert_eq!(Some(("a", "b c")), env); - - let env = valid_env("=b"); - assert_eq!(None, env); - - let env = valid_env("a="); - assert_eq!(Some(("a", "")), env); - - let env = valid_env("a=="); - assert_eq!(Some(("a", "=")), env); - - let env = valid_env("a"); - assert_eq!(None, env); - - let invalid_str = vec![97, b'\0', 98]; - let invalid_string = std::str::from_utf8(&invalid_str).unwrap(); - - let invalid_env = format!("{}=value", invalid_string); - let env = valid_env(&invalid_env); - assert_eq!(None, env); - - let invalid_env = format!("key={}", invalid_string); - let env = valid_env(&invalid_env); - assert_eq!(None, env); - } } diff --git a/src/libs/Cargo.lock b/src/libs/Cargo.lock index 66090c19c55a..90423e00231b 100644 --- a/src/libs/Cargo.lock +++ b/src/libs/Cargo.lock @@ -40,6 +40,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "bitflags" version = "1.2.1" @@ -420,6 +426,8 @@ dependencies = [ name = "kata-types" version = "0.1.0" dependencies = [ + "anyhow", + "base64", "bitmask-enum", "byte-unit", "glob", diff --git a/src/libs/kata-sys-util/src/hooks.rs b/src/libs/kata-sys-util/src/hooks.rs index 78e3ae662ed9..8a36e606e1a8 100644 --- a/src/libs/kata-sys-util/src/hooks.rs +++ b/src/libs/kata-sys-util/src/hooks.rs @@ -13,6 +13,7 @@ use std::time::Duration; use subprocess::{ExitStatus, Popen, PopenConfig, PopenError, Redirection}; +use crate::validate::valid_env; use crate::{eother, sl}; const DEFAULT_HOOK_TIMEOUT_SEC: i32 = 10; @@ -206,9 +207,8 @@ impl<'a> HookExecutor<'a> { let mut envs: Vec<(OsString, OsString)> = Vec::new(); for e in hook.env.iter() { - match e.split_once('=') { - Some((key, value)) => envs.push((OsString::from(key), OsString::from(value))), - None => warn!(sl!(), "env {} of hook {:?} is invalid", e, hook), + if let Some((key, value)) = valid_env(e) { + envs.push((OsString::from(key), OsString::from(value))); } } diff --git a/src/libs/kata-sys-util/src/validate.rs b/src/libs/kata-sys-util/src/validate.rs index 0847398cefe2..8348b0eb5f10 100644 --- a/src/libs/kata-sys-util/src/validate.rs +++ b/src/libs/kata-sys-util/src/validate.rs @@ -34,6 +34,27 @@ pub fn verify_id(id: &str) -> Result<(), Error> { } } +// check and reserve valid environment variables +// invalid env var may cause panic, refer to https://doc.rust-lang.org/std/env/fn.set_var.html#panics +// key should not: +// * contain NUL character '\0' +// * contain ASCII equal sign '=' +// * be empty +// value should not: +// * contain NUL character '\0' +pub fn valid_env(e: &str) -> Option<(&str, &str)> { + // split the env str by '=' at the first time to ensure there is no '=' in key, + // and also to ensure there is at least '=' in env str + if let Some((key, value)) = e.split_once('=') { + if !key.is_empty() && !key.as_bytes().contains(&b'\0') && !value.as_bytes().contains(&b'\0') + { + return Some((key.trim(), value.trim())); + } + } + + None +} + #[cfg(test)] mod tests { use super::*; @@ -264,4 +285,49 @@ mod tests { } } } + + #[test] + fn test_valid_env() { + let env = valid_env("a=b=c"); + assert_eq!(Some(("a", "b=c")), env); + + let env = valid_env("a=b"); + assert_eq!(Some(("a", "b")), env); + let env = valid_env("a =b"); + assert_eq!(Some(("a", "b")), env); + + let env = valid_env(" a =b"); + assert_eq!(Some(("a", "b")), env); + + let env = valid_env("a= b"); + assert_eq!(Some(("a", "b")), env); + + let env = valid_env("a=b "); + assert_eq!(Some(("a", "b")), env); + let env = valid_env("a=b c "); + assert_eq!(Some(("a", "b c")), env); + + let env = valid_env("=b"); + assert_eq!(None, env); + + let env = valid_env("a="); + assert_eq!(Some(("a", "")), env); + + let env = valid_env("a=="); + assert_eq!(Some(("a", "=")), env); + + let env = valid_env("a"); + assert_eq!(None, env); + + let invalid_str = vec![97, b'\0', 98]; + let invalid_string = std::str::from_utf8(&invalid_str).unwrap(); + + let invalid_env = format!("{}=value", invalid_string); + let env = valid_env(&invalid_env); + assert_eq!(None, env); + + let invalid_env = format!("key={}", invalid_string); + let env = valid_env(&invalid_env); + assert_eq!(None, env); + } } diff --git a/src/tools/runk/Cargo.lock b/src/tools/runk/Cargo.lock index fb22c2845106..6c498c328290 100644 --- a/src/tools/runk/Cargo.lock +++ b/src/tools/runk/Cargo.lock @@ -139,6 +139,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "bit-vec" version = "0.6.3" @@ -151,6 +157,22 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitmask-enum" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd9e32d7420c85055e8107e5b2463c4eeefeaac18b52359fe9f9c08a18f342b2" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "byte-unit" +version = "3.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415301c9de11005d4b92193c0eb7ac7adc37e5a49e0ac9bed0a42343512744b8" + [[package]] name = "byteorder" version = "1.4.3" @@ -274,6 +296,12 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "common-path" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2382f75942f4b3be3690fe4f86365e9c853c1587d6ee58212cebf6e2a9ccd101" + [[package]] name = "concurrent-queue" version = "1.2.4" @@ -474,6 +502,17 @@ version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +[[package]] +name = "fail" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe5e43d0f78a42ad591453aedb1d7ae631ce7ee445c7643691055a9ed8d3b01c" +dependencies = [ + "log", + "once_cell", + "rand 0.8.5", +] + [[package]] name = "fastrand" version = "1.7.0" @@ -609,6 +648,17 @@ dependencies = [ "slab", ] +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + [[package]] name = "getrandom" version = "0.2.7" @@ -620,6 +670,12 @@ dependencies = [ "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + [[package]] name = "hashbrown" version = "0.11.2" @@ -724,6 +780,50 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +[[package]] +name = "kata-sys-util" +version = "0.1.0" +dependencies = [ + "byteorder", + "cgroups-rs", + "chrono", + "common-path", + "fail", + "kata-types", + "lazy_static", + "libc", + "nix 0.24.2", + "oci", + "once_cell", + "rand 0.7.3", + "serde_json", + "slog", + "slog-scope", + "subprocess", + "thiserror", +] + +[[package]] +name = "kata-types" +version = "0.1.0" +dependencies = [ + "anyhow", + "base64", + "bitmask-enum", + "byte-unit", + "glob", + "lazy_static", + "num_cpus", + "oci", + "regex", + "serde", + "serde_json", + "slog", + "slog-scope", + "thiserror", + "toml", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -744,6 +844,7 @@ dependencies = [ "cgroups-rs", "chrono", "derive_builder", + "kata-sys-util", "libc", "logging", "nix 0.23.1", @@ -1232,6 +1333,19 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + [[package]] name = "rand" version = "0.8.5" @@ -1239,8 +1353,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.3", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", ] [[package]] @@ -1250,7 +1374,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.3", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", ] [[package]] @@ -1259,7 +1392,16 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom", + "getrandom 0.2.7", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", ] [[package]] @@ -1277,7 +1419,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom", + "getrandom 0.2.7", "redox_syscall", "thiserror", ] @@ -1368,6 +1510,7 @@ dependencies = [ "cgroups-rs", "futures", "inotify", + "kata-sys-util", "lazy_static", "libc", "libseccomp", @@ -1557,6 +1700,16 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "subprocess" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c2e86926081dda636c546d8c5e641661049d7562a68f5488be4a1f7f66f6086" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "syn" version = "1.0.91" @@ -1834,6 +1987,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + [[package]] name = "wasi" version = "0.10.0+wasi-snapshot-preview1" @@ -2010,7 +2169,7 @@ dependencies = [ "nix 0.23.1", "once_cell", "ordered-stream", - "rand", + "rand 0.8.5", "serde", "serde_repr", "sha1", diff --git a/src/tools/runk/libcontainer/Cargo.toml b/src/tools/runk/libcontainer/Cargo.toml index 0db70d3d179c..5c92a5b979d1 100644 --- a/src/tools/runk/libcontainer/Cargo.toml +++ b/src/tools/runk/libcontainer/Cargo.toml @@ -9,6 +9,7 @@ edition = "2018" [dependencies] rustjail = { path = "../../../agent/rustjail", features = ["standard-oci-runtime"] } oci = { path = "../../../libs/oci" } +kata-sys-util = { path = "../../../libs/kata-sys-util" } logging = { path = "../../../libs/logging" } derive_builder = "0.10.2" libc = "0.2.108" diff --git a/src/tools/runk/libcontainer/src/container.rs b/src/tools/runk/libcontainer/src/container.rs index 20bad5d82655..1bc8307cf9a7 100644 --- a/src/tools/runk/libcontainer/src/container.rs +++ b/src/tools/runk/libcontainer/src/container.rs @@ -19,18 +19,20 @@ use oci::{ContainerState, State as OCIState}; use procfs; use rustjail::cgroups::fs::Manager as CgroupManager; use rustjail::{ - container::{self, BaseContainer, LinuxContainer, EXEC_FIFO_FILENAME}, + container::{BaseContainer, LinuxContainer, EXEC_FIFO_FILENAME}, process::{Process, ProcessOperations}, specconv::CreateOpts, }; use scopeguard::defer; -use slog::{debug, Logger}; +use slog::{debug, info, Logger}; use std::{ env::current_dir, fs, path::{Path, PathBuf}, }; +use kata_sys_util::hooks::HookStates; + pub const CONFIG_FILE_NAME: &str = "config.json"; #[derive(Debug, Copy, Clone, PartialEq)] @@ -139,14 +141,10 @@ impl Container { annotations: spec.annotations.clone(), }; - if spec.hooks.is_some() { - let hooks = spec - .hooks - .as_ref() - .ok_or_else(|| anyhow!("hooks config was not present"))?; - for h in hooks.poststop.iter() { - container::execute_hook(logger, h, &oci_state).await?; - } + if let Some(hooks) = spec.hooks.as_ref() { + info!(&logger, "Poststop Hooks"); + let mut poststop_hookstates = HookStates::new(); + poststop_hookstates.execute_hooks(&hooks.poststop, Some(oci_state.clone()))?; } match oci_state.status {