agent: Log unknown seccomp system calls

Kata agent logs unknown system calls given by seccomp profiles
in advance before the log file descriptor closes.

Fixes: #2957

Signed-off-by: Manabu Sugimoto <Manabu.Sugimoto@sony.com>
This commit is contained in:
Manabu Sugimoto 2021-11-05 21:00:03 +09:00
parent c66b56683b
commit 7b35615191
2 changed files with 101 additions and 65 deletions

View File

@ -600,6 +600,14 @@ fn do_init_child(cwfd: RawFd) -> Result<()> {
capctl::prctl::set_no_new_privs().map_err(|_| anyhow!("cannot set no new privileges"))?; capctl::prctl::set_no_new_privs().map_err(|_| anyhow!("cannot set no new privileges"))?;
} }
// Log unknown seccomp system calls in advance before the log file descriptor closes.
#[cfg(feature = "seccomp")]
if let Some(ref scmp) = linux.seccomp {
if let Some(syscalls) = seccomp::get_unknown_syscalls(scmp) {
log_child!(cfd_log, "unknown seccomp system calls: {:?}", syscalls);
}
}
// Without NoNewPrivileges, we need to set seccomp // Without NoNewPrivileges, we need to set seccomp
// before dropping capabilities because the calling thread // before dropping capabilities because the calling thread
// must have the CAP_SYS_ADMIN. // must have the CAP_SYS_ADMIN.

View File

@ -39,6 +39,24 @@ fn get_rule_conditions(args: &[LinuxSeccompArg]) -> Result<Vec<ScmpArgCompare>>
Ok(conditions) Ok(conditions)
} }
pub fn get_unknown_syscalls(scmp: &LinuxSeccomp) -> Option<Vec<String>> {
let mut unknown_syscalls: Vec<String> = Vec::new();
for syscall in &scmp.syscalls {
for name in &syscall.names {
if get_syscall_from_name(name, None).is_err() {
unknown_syscalls.push(name.to_string());
}
}
}
if unknown_syscalls.is_empty() {
None
} else {
Some(unknown_syscalls)
}
}
// init_seccomp creates a seccomp filter and loads it for the current process // init_seccomp creates a seccomp filter and loads it for the current process
// including all the child processes. // including all the child processes.
pub fn init_seccomp(scmp: &LinuxSeccomp) -> Result<()> { pub fn init_seccomp(scmp: &LinuxSeccomp) -> Result<()> {
@ -116,23 +134,7 @@ mod tests {
}; };
} }
#[test] const TEST_DATA: &str = r#"{
fn test_get_filter_attr_from_flag() {
skip_if_not_root!();
assert_eq!(
get_filter_attr_from_flag("SECCOMP_FILTER_FLAG_TSYNC").unwrap(),
ScmpFilterAttr::CtlTsync
);
assert_eq!(get_filter_attr_from_flag("ERROR").is_err(), true);
}
#[test]
fn test_init_seccomp() {
skip_if_not_root!();
let data = r#"{
"defaultAction": "SCMP_ACT_ALLOW", "defaultAction": "SCMP_ACT_ALLOW",
"architectures": [ "architectures": [
], ],
@ -142,7 +144,9 @@ mod tests {
"syscalls": [ "syscalls": [
{ {
"names": [ "names": [
"dup3" "dup3",
"invalid_syscall1",
"invalid_syscall2"
], ],
"action": "SCMP_ACT_ERRNO" "action": "SCMP_ACT_ERRNO"
}, },
@ -196,7 +200,31 @@ mod tests {
] ]
}"#; }"#;
let mut scmp: oci::LinuxSeccomp = serde_json::from_str(data).unwrap(); #[test]
fn test_get_filter_attr_from_flag() {
skip_if_not_root!();
assert_eq!(
get_filter_attr_from_flag("SECCOMP_FILTER_FLAG_TSYNC").unwrap(),
ScmpFilterAttr::CtlTsync
);
assert_eq!(get_filter_attr_from_flag("ERROR").is_err(), true);
}
#[test]
fn test_get_unknown_syscalls() {
let scmp: oci::LinuxSeccomp = serde_json::from_str(TEST_DATA).unwrap();
let syscalls = get_unknown_syscalls(&scmp).unwrap();
assert_eq!(syscalls, vec!["invalid_syscall1", "invalid_syscall2"]);
}
#[test]
fn test_init_seccomp() {
skip_if_not_root!();
let mut scmp: oci::LinuxSeccomp = serde_json::from_str(TEST_DATA).unwrap();
let mut arch: Vec<oci::Arch>; let mut arch: Vec<oci::Arch>;
if cfg!(target_endian = "little") { if cfg!(target_endian = "little") {