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 <y-shuo@linux.alibaba.com>
This commit is contained in:
Yushuo 2022-12-04 16:24:49 +08:00
parent 39394fa2a8
commit 85f9094f17
9 changed files with 281 additions and 333 deletions

1
src/agent/Cargo.lock generated
View File

@ -1684,6 +1684,7 @@ dependencies = [
"cgroups-rs", "cgroups-rs",
"futures", "futures",
"inotify", "inotify",
"kata-sys-util",
"lazy_static", "lazy_static",
"libc", "libc",
"libseccomp", "libseccomp",

View File

@ -11,6 +11,7 @@ serde_json = "1.0.39"
serde_derive = "1.0.91" serde_derive = "1.0.91"
oci = { path = "../../libs/oci" } oci = { path = "../../libs/oci" }
protocols = { path ="../../libs/protocols" } protocols = { path ="../../libs/protocols" }
kata-sys-util = { path = "../../libs/kata-sys-util" }
caps = "0.5.0" caps = "0.5.0"
nix = "0.24.2" nix = "0.24.2"
scopeguard = "1.0.0" scopeguard = "1.0.0"

View File

@ -6,7 +6,7 @@
use anyhow::{anyhow, Context, Result}; use anyhow::{anyhow, Context, Result};
use libc::pid_t; use libc::pid_t;
use oci::{ContainerState, LinuxDevice, LinuxIdMapping}; use oci::{ContainerState, LinuxDevice, LinuxIdMapping};
use oci::{Hook, Linux, LinuxNamespace, LinuxResources, Spec}; use oci::{Linux, LinuxNamespace, LinuxResources, Spec};
use std::clone::Clone; use std::clone::Clone;
use std::ffi::CString; use std::ffi::CString;
use std::fmt::Display; use std::fmt::Display;
@ -66,6 +66,9 @@ use rlimit::{setrlimit, Resource, Rlim};
use tokio::io::AsyncBufReadExt; use tokio::io::AsyncBufReadExt;
use tokio::sync::Mutex; 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"; pub const EXEC_FIFO_FILENAME: &str = "exec.fifo";
const INIT: &str = "INIT"; const INIT: &str = "INIT";
@ -1099,12 +1102,14 @@ impl BaseContainer for LinuxContainer {
} }
} }
if spec.hooks.is_some() { // guest Poststop hook
info!(self.logger, "poststop"); // * should be executed after the container is deleted but before the delete operation returns
let hooks = spec.hooks.as_ref().unwrap(); // * the executable file is in agent namespace
for h in hooks.poststop.iter() { // * should also be executed in agent namespace.
execute_hook(&self.logger, h, &st).await?; 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); self.status.transition(ContainerState::Stopped);
@ -1150,16 +1155,14 @@ impl BaseContainer for LinuxContainer {
.ok_or_else(|| anyhow!("OCI spec was not found"))?; .ok_or_else(|| anyhow!("OCI spec was not found"))?;
let st = self.oci_state()?; let st = self.oci_state()?;
// run poststart hook // guest Poststart hook
if spec.hooks.is_some() { // * should be executed after the container is started but before the delete operation returns
info!(self.logger, "poststart hook"); // * the executable file is in agent namespace
let hooks = spec // * should also be executed in agent namespace.
.hooks if let Some(hooks) = spec.hooks.as_ref() {
.as_ref() info!(self.logger, "guest Poststart hook");
.ok_or_else(|| anyhow!("OCI hooks were not found"))?; let mut hook_states = HookStates::new();
for h in hooks.poststart.iter() { hook_states.execute_hooks(&hooks.poststart, Some(st))?;
execute_hook(&self.logger, h, &st).await?;
}
} }
unistd::close(fd)?; unistd::close(fd)?;
@ -1380,13 +1383,14 @@ async fn join_namespaces(
info!(logger, "get ready to run prestart hook!"); info!(logger, "get ready to run prestart hook!");
// run prestart hook // guest Prestart hook
if spec.hooks.is_some() { // * should be executed during the start operation, and before the container command is executed
info!(logger, "prestart hook"); // * the executable file is in agent namespace
let hooks = spec.hooks.as_ref().unwrap(); // * should also be executed in agent namespace.
for h in hooks.prestart.iter() { if let Some(hooks) = spec.hooks.as_ref() {
execute_hook(&logger, h, st).await?; 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 // notify child run prestart hooks completed
@ -1566,143 +1570,6 @@ fn set_sysctls(sysctls: &HashMap<String, String>) -> Result<()> {
Ok(()) 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)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@ -1713,7 +1580,6 @@ mod tests {
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use tempfile::tempdir; use tempfile::tempdir;
use test_utils::skip_if_not_root; use test_utils::skip_if_not_root;
use tokio::process::Command;
macro_rules! sl { 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::<nix::Error>().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::<nix::Error>().unwrap(),
expected_err
);
}
#[test] #[test]
fn test_status_transtition() { fn test_status_transtition() {
let mut status = ContainerStatus::new(); let mut status = ContainerStatus::new();
@ -2167,49 +1926,4 @@ mod tests {
let ret = do_init_child(std::io::stdin().as_raw_fd()); let ret = do_init_child(std::io::stdin().as_raw_fd());
assert!(ret.is_err(), "Expecting Err, Got {:?}", ret); 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);
}
} }

8
src/libs/Cargo.lock generated
View File

@ -40,6 +40,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "base64"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.2.1" version = "1.2.1"
@ -420,6 +426,8 @@ dependencies = [
name = "kata-types" name = "kata-types"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow",
"base64",
"bitmask-enum", "bitmask-enum",
"byte-unit", "byte-unit",
"glob", "glob",

View File

@ -13,6 +13,7 @@ use std::time::Duration;
use subprocess::{ExitStatus, Popen, PopenConfig, PopenError, Redirection}; use subprocess::{ExitStatus, Popen, PopenConfig, PopenError, Redirection};
use crate::validate::valid_env;
use crate::{eother, sl}; use crate::{eother, sl};
const DEFAULT_HOOK_TIMEOUT_SEC: i32 = 10; const DEFAULT_HOOK_TIMEOUT_SEC: i32 = 10;
@ -206,9 +207,8 @@ impl<'a> HookExecutor<'a> {
let mut envs: Vec<(OsString, OsString)> = Vec::new(); let mut envs: Vec<(OsString, OsString)> = Vec::new();
for e in hook.env.iter() { for e in hook.env.iter() {
match e.split_once('=') { if let Some((key, value)) = valid_env(e) {
Some((key, value)) => envs.push((OsString::from(key), OsString::from(value))), envs.push((OsString::from(key), OsString::from(value)));
None => warn!(sl!(), "env {} of hook {:?} is invalid", e, hook),
} }
} }

View File

@ -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)] #[cfg(test)]
mod tests { mod tests {
use super::*; 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);
}
} }

View File

@ -139,6 +139,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "base64"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]] [[package]]
name = "bit-vec" name = "bit-vec"
version = "0.6.3" version = "0.6.3"
@ -151,6 +157,22 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 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]] [[package]]
name = "byteorder" name = "byteorder"
version = "1.4.3" version = "1.4.3"
@ -274,6 +296,12 @@ dependencies = [
"os_str_bytes", "os_str_bytes",
] ]
[[package]]
name = "common-path"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2382f75942f4b3be3690fe4f86365e9c853c1587d6ee58212cebf6e2a9ccd101"
[[package]] [[package]]
name = "concurrent-queue" name = "concurrent-queue"
version = "1.2.4" version = "1.2.4"
@ -474,6 +502,17 @@ version = "2.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" 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]] [[package]]
name = "fastrand" name = "fastrand"
version = "1.7.0" version = "1.7.0"
@ -609,6 +648,17 @@ dependencies = [
"slab", "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]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.7" version = "0.2.7"
@ -620,6 +670,12 @@ dependencies = [
"wasi 0.11.0+wasi-snapshot-preview1", "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]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.11.2" version = "0.11.2"
@ -724,6 +780,50 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" 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]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.4.0" version = "1.4.0"
@ -744,6 +844,7 @@ dependencies = [
"cgroups-rs", "cgroups-rs",
"chrono", "chrono",
"derive_builder", "derive_builder",
"kata-sys-util",
"libc", "libc",
"logging", "logging",
"nix 0.23.1", "nix 0.23.1",
@ -1232,6 +1333,19 @@ dependencies = [
"proc-macro2", "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]] [[package]]
name = "rand" name = "rand"
version = "0.8.5" version = "0.8.5"
@ -1239,8 +1353,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [ dependencies = [
"libc", "libc",
"rand_chacha", "rand_chacha 0.3.1",
"rand_core", "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]] [[package]]
@ -1250,7 +1374,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [ dependencies = [
"ppv-lite86", "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]] [[package]]
@ -1259,7 +1392,16 @@ version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
dependencies = [ 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]] [[package]]
@ -1277,7 +1419,7 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
dependencies = [ dependencies = [
"getrandom", "getrandom 0.2.7",
"redox_syscall", "redox_syscall",
"thiserror", "thiserror",
] ]
@ -1368,6 +1510,7 @@ dependencies = [
"cgroups-rs", "cgroups-rs",
"futures", "futures",
"inotify", "inotify",
"kata-sys-util",
"lazy_static", "lazy_static",
"libc", "libc",
"libseccomp", "libseccomp",
@ -1557,6 +1700,16 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 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]] [[package]]
name = "syn" name = "syn"
version = "1.0.91" version = "1.0.91"
@ -1834,6 +1987,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" 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]] [[package]]
name = "wasi" name = "wasi"
version = "0.10.0+wasi-snapshot-preview1" version = "0.10.0+wasi-snapshot-preview1"
@ -2010,7 +2169,7 @@ dependencies = [
"nix 0.23.1", "nix 0.23.1",
"once_cell", "once_cell",
"ordered-stream", "ordered-stream",
"rand", "rand 0.8.5",
"serde", "serde",
"serde_repr", "serde_repr",
"sha1", "sha1",

View File

@ -9,6 +9,7 @@ edition = "2018"
[dependencies] [dependencies]
rustjail = { path = "../../../agent/rustjail", features = ["standard-oci-runtime"] } rustjail = { path = "../../../agent/rustjail", features = ["standard-oci-runtime"] }
oci = { path = "../../../libs/oci" } oci = { path = "../../../libs/oci" }
kata-sys-util = { path = "../../../libs/kata-sys-util" }
logging = { path = "../../../libs/logging" } logging = { path = "../../../libs/logging" }
derive_builder = "0.10.2" derive_builder = "0.10.2"
libc = "0.2.108" libc = "0.2.108"

View File

@ -19,18 +19,20 @@ use oci::{ContainerState, State as OCIState};
use procfs; use procfs;
use rustjail::cgroups::fs::Manager as CgroupManager; use rustjail::cgroups::fs::Manager as CgroupManager;
use rustjail::{ use rustjail::{
container::{self, BaseContainer, LinuxContainer, EXEC_FIFO_FILENAME}, container::{BaseContainer, LinuxContainer, EXEC_FIFO_FILENAME},
process::{Process, ProcessOperations}, process::{Process, ProcessOperations},
specconv::CreateOpts, specconv::CreateOpts,
}; };
use scopeguard::defer; use scopeguard::defer;
use slog::{debug, Logger}; use slog::{debug, info, Logger};
use std::{ use std::{
env::current_dir, env::current_dir,
fs, fs,
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
use kata_sys_util::hooks::HookStates;
pub const CONFIG_FILE_NAME: &str = "config.json"; pub const CONFIG_FILE_NAME: &str = "config.json";
#[derive(Debug, Copy, Clone, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq)]
@ -139,14 +141,10 @@ impl Container {
annotations: spec.annotations.clone(), annotations: spec.annotations.clone(),
}; };
if spec.hooks.is_some() { if let Some(hooks) = spec.hooks.as_ref() {
let hooks = spec info!(&logger, "Poststop Hooks");
.hooks let mut poststop_hookstates = HookStates::new();
.as_ref() poststop_hookstates.execute_hooks(&hooks.poststop, Some(oci_state.clone()))?;
.ok_or_else(|| anyhow!("hooks config was not present"))?;
for h in hooks.poststop.iter() {
container::execute_hook(logger, h, &oci_state).await?;
}
} }
match oci_state.status { match oci_state.status {