diff --git a/cloud-hypervisor/src/main.rs b/cloud-hypervisor/src/main.rs index c773a3c01..0c9b3d12e 100644 --- a/cloud-hypervisor/src/main.rs +++ b/cloud-hypervisor/src/main.rs @@ -454,7 +454,7 @@ fn get_cli_options_sorted( Arg::new("seccomp") .long("seccomp") .num_args(1) - .value_parser(["true", "false", "log"]) + .value_parser(["true", "false", "log", "errno"]) .default_value("true"), Arg::new("serial") .long("serial") @@ -588,6 +588,7 @@ fn start_vmm( "true" => SeccompAction::Trap, "false" => SeccompAction::Allow, "log" => SeccompAction::Log, + "errno" => SeccompAction::Errno(libc::EPERM as u32), val => { // The user providing an invalid value will be rejected panic!("Invalid parameter {val} for \"--seccomp\" flag"); diff --git a/docs/seccomp.md b/docs/seccomp.md index 4668b35cd..1370fc9f7 100644 --- a/docs/seccomp.md +++ b/docs/seccomp.md @@ -57,6 +57,22 @@ $ ausyscall 47 recvmsg ``` +### Returning EPERM instead of killing the VMM + +Append `--seccomp errno` to make prohibited system calls return `EPERM` to the +caller instead of terminating the process. This lets the VMM keep running so a +regression caused by an unknown syscall can be observed without an immediate +crash, at the cost of turning the violation into a soft failure visible only as +a syscall error. + +By default the kernel does not log `errno` actions. To audit them, ensure +`errno` is included in the host's `kernel.seccomp.actions_logged` sysctl, for +example: + +``` +# sysctl -w kernel.seccomp.actions_logged='kill_process kill_thread trap errno log' +``` + ### Further debug with `strace` One more way of debugging seccomp related issues is to use the `strace` tool as diff --git a/virtio-devices/src/seccomp_filters.rs b/virtio-devices/src/seccomp_filters.rs index b9b30c94d..75f493448 100644 --- a/virtio-devices/src/seccomp_filters.rs +++ b/virtio-devices/src/seccomp_filters.rs @@ -380,17 +380,9 @@ pub fn get_seccomp_filter( ) -> Result { match seccomp_action { SeccompAction::Allow => Ok(vec![]), - SeccompAction::Log => SeccompFilter::new( - get_seccomp_rules(thread_type).into_iter().collect(), - SeccompAction::Log, - SeccompAction::Allow, - env::consts::ARCH.try_into().unwrap(), - ) - .and_then(|filter| filter.try_into()) - .map_err(Error::Backend), _ => SeccompFilter::new( get_seccomp_rules(thread_type).into_iter().collect(), - SeccompAction::Trap, + seccomp_action.clone(), SeccompAction::Allow, env::consts::ARCH.try_into().unwrap(), ) diff --git a/vmm/src/seccomp_filters.rs b/vmm/src/seccomp_filters.rs index eaca582ac..308cfa6bf 100644 --- a/vmm/src/seccomp_filters.rs +++ b/vmm/src/seccomp_filters.rs @@ -1249,23 +1249,12 @@ pub fn get_seccomp_filter( ) -> Result { match seccomp_action { SeccompAction::Allow => Ok(vec![]), - SeccompAction::Log => SeccompFilter::new( - get_seccomp_rules(thread_type, hypervisor_type) - .map_err(Error::Backend)? - .into_iter() - .collect(), - SeccompAction::Log, - SeccompAction::Allow, - consts::ARCH.try_into().unwrap(), - ) - .and_then(|filter| filter.try_into()) - .map_err(Error::Backend), _ => SeccompFilter::new( get_seccomp_rules(thread_type, hypervisor_type) .map_err(Error::Backend)? .into_iter() .collect(), - SeccompAction::Trap, + seccomp_action.clone(), SeccompAction::Allow, consts::ARCH.try_into().unwrap(), )