main, vmm: seccomp: Add the '--seccomp log' option

This patch extends the CLI option '--seccomp' to accept the 'log'
parameter in addition 'true/false'. It also refactors the
vmm::seccomp_filters module to support both "SeccompAction::Trap" and
"SeccompAction::Log".

Fixes: #1180

Signed-off-by: Bo Chen <chen.bo@intel.com>
This commit is contained in:
Bo Chen 2020-08-03 19:39:07 -07:00 committed by Sebastien Boeuf
parent b41884a406
commit 8e74637ebb
2 changed files with 156 additions and 141 deletions

View File

@ -260,7 +260,7 @@ fn create_app<'a, 'b>(
Arg::with_name("seccomp") Arg::with_name("seccomp")
.long("seccomp") .long("seccomp")
.takes_value(true) .takes_value(true)
.possible_values(&["true", "false"]) .possible_values(&["true", "false", "log"])
.default_value("true"), .default_value("true"),
); );
@ -292,6 +292,7 @@ fn start_vmm(cmd_arguments: ArgMatches) {
match seccomp_value { match seccomp_value {
"true" => SeccompAction::Trap, "true" => SeccompAction::Trap,
"false" => SeccompAction::Allow, "false" => SeccompAction::Allow,
"log" => SeccompAction::Log,
_ => { _ => {
eprintln!("Invalid parameter {} for \"--seccomp\" flag", seccomp_value); eprintln!("Invalid parameter {} for \"--seccomp\" flag", seccomp_value);
process::exit(1); process::exit(1);

View File

@ -7,6 +7,7 @@
use seccomp::{ use seccomp::{
allow_syscall, allow_syscall_if, BpfProgram, Error, SeccompAction, SeccompCmpArgLen as ArgLen, allow_syscall, allow_syscall_if, BpfProgram, Error, SeccompAction, SeccompCmpArgLen as ArgLen,
SeccompCmpOp::Eq, SeccompCondition as Cond, SeccompError, SeccompFilter, SeccompRule, SeccompCmpOp::Eq, SeccompCondition as Cond, SeccompError, SeccompFilter, SeccompRule,
SyscallRuleSet,
}; };
use std::convert::TryInto; use std::convert::TryInto;
@ -236,11 +237,10 @@ fn create_api_ioctl_seccomp_rule() -> Result<Vec<SeccompRule>, Error> {
Ok(or![and![Cond::new(1, ArgLen::DWORD, Eq, FIONBIO)?],]) Ok(or![and![Cond::new(1, ArgLen::DWORD, Eq, FIONBIO)?],])
} }
/// The filter containing the white listed syscall rules required by the VMM to // The filter containing the white listed syscall rules required by the VMM to
/// function. // function.
pub fn vmm_thread_filter() -> Result<SeccompFilter, Error> { fn vmm_thread_rules() -> Result<Vec<SyscallRuleSet>, Error> {
Ok(SeccompFilter::new( Ok(vec![
vec![
allow_syscall(libc::SYS_accept4), allow_syscall(libc::SYS_accept4),
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
allow_syscall(libc::SYS_access), allow_syscall(libc::SYS_access),
@ -341,18 +341,13 @@ pub fn vmm_thread_filter() -> Result<SeccompFilter, Error> {
allow_syscall(libc::SYS_unlinkat), allow_syscall(libc::SYS_unlinkat),
allow_syscall(libc::SYS_wait4), allow_syscall(libc::SYS_wait4),
allow_syscall(libc::SYS_write), allow_syscall(libc::SYS_write),
] ])
.into_iter()
.collect(),
SeccompAction::Trap,
)?)
} }
/// The filter containing the white listed syscall rules required by the API to // The filter containing the white listed syscall rules required by the API to
/// function. // function.
pub fn api_thread_filter() -> Result<SeccompFilter, Error> { fn api_thread_rules() -> Result<Vec<SyscallRuleSet>, Error> {
Ok(SeccompFilter::new( Ok(vec![
vec![
allow_syscall(libc::SYS_accept4), allow_syscall(libc::SYS_accept4),
allow_syscall(libc::SYS_bind), allow_syscall(libc::SYS_bind),
allow_syscall(libc::SYS_close), allow_syscall(libc::SYS_close),
@ -373,25 +368,44 @@ pub fn api_thread_filter() -> Result<SeccompFilter, Error> {
allow_syscall(libc::SYS_sigaltstack), allow_syscall(libc::SYS_sigaltstack),
allow_syscall(libc::SYS_socket), allow_syscall(libc::SYS_socket),
allow_syscall(libc::SYS_write), allow_syscall(libc::SYS_write),
] ])
.into_iter() }
.collect(),
fn get_seccomp_filter_trap(thread_type: Thread) -> Result<SeccompFilter, Error> {
let rules = match thread_type {
Thread::Vmm => vmm_thread_rules()?,
Thread::Api => api_thread_rules()?,
};
Ok(SeccompFilter::new(
rules.into_iter().collect(),
SeccompAction::Trap, SeccompAction::Trap,
)?) )?)
} }
fn get_seccomp_filter_log(thread_type: Thread) -> Result<SeccompFilter, Error> {
let rules = match thread_type {
Thread::Vmm => vmm_thread_rules()?,
Thread::Api => api_thread_rules()?,
};
Ok(SeccompFilter::new(
rules.into_iter().collect(),
SeccompAction::Log,
)?)
}
/// Generate a BPF program based on the seccomp_action value /// Generate a BPF program based on the seccomp_action value
pub fn get_seccomp_filter( pub fn get_seccomp_filter(
seccomp_action: &SeccompAction, seccomp_action: &SeccompAction,
thread_type: Thread, thread_type: Thread,
) -> Result<BpfProgram, SeccompError> { ) -> Result<BpfProgram, SeccompError> {
let filter = match thread_type {
Thread::Vmm => vmm_thread_filter(),
Thread::Api => api_thread_filter(),
};
match seccomp_action { match seccomp_action {
SeccompAction::Allow => Ok(vec![]), SeccompAction::Allow => Ok(vec![]),
_ => filter SeccompAction::Log => get_seccomp_filter_log(thread_type)
.and_then(|filter| filter.try_into())
.map_err(SeccompError::SeccompFilter),
_ => get_seccomp_filter_trap(thread_type)
.and_then(|filter| filter.try_into()) .and_then(|filter| filter.try_into())
.map_err(SeccompError::SeccompFilter), .map_err(SeccompError::SeccompFilter),
} }