From 9682d74763d37ada6b18a41c350e14bee93abfc9 Mon Sep 17 00:00:00 2001 From: Bo Chen Date: Wed, 9 Sep 2020 16:33:58 -0700 Subject: [PATCH] vmm: seccomp: Add seccomp filters for signal_handler worker thread This patch covers the last worker thread with dedicated secomp filters. Fixes: #925 Signed-off-by: Bo Chen --- vmm/src/seccomp_filters.rs | 25 +++++++++++++++++++++ vmm/src/vm.rs | 46 +++++++++++++++++++++++++++++++++++--- 2 files changed, 68 insertions(+), 3 deletions(-) diff --git a/vmm/src/seccomp_filters.rs b/vmm/src/seccomp_filters.rs index cb6838986..acb6f1a60 100644 --- a/vmm/src/seccomp_filters.rs +++ b/vmm/src/seccomp_filters.rs @@ -13,6 +13,7 @@ use std::convert::TryInto; pub enum Thread { Api, + SignalHandler, Vcpu, Vmm, } @@ -238,6 +239,28 @@ fn create_api_ioctl_seccomp_rule() -> Result, Error> { Ok(or![and![Cond::new(1, ArgLen::DWORD, Eq, FIONBIO)?],]) } +fn create_signal_handler_ioctl_seccomp_rule() -> Result, Error> { + Ok(or![and![Cond::new(1, ArgLen::DWORD, Eq, TIOCGWINSZ)?],]) +} + +fn signal_handler_thread_rules() -> Result, Error> { + Ok(vec![ + allow_syscall(libc::SYS_brk), + allow_syscall(libc::SYS_close), + allow_syscall(libc::SYS_exit), + allow_syscall(libc::SYS_exit_group), + allow_syscall(libc::SYS_futex), + allow_syscall_if(libc::SYS_ioctl, create_signal_handler_ioctl_seccomp_rule()?), + allow_syscall(libc::SYS_madvise), + allow_syscall(libc::SYS_munmap), + allow_syscall(libc::SYS_recvfrom), + allow_syscall(libc::SYS_rt_sigprocmask), + allow_syscall(libc::SYS_sendto), + allow_syscall(libc::SYS_sigaltstack), + allow_syscall(libc::SYS_write), + ]) +} + // The filter containing the white listed syscall rules required by the VMM to // function. fn vmm_thread_rules() -> Result, Error> { @@ -460,6 +483,7 @@ fn api_thread_rules() -> Result, Error> { fn get_seccomp_filter_trap(thread_type: Thread) -> Result { let rules = match thread_type { Thread::Api => api_thread_rules()?, + Thread::SignalHandler => signal_handler_thread_rules()?, Thread::Vcpu => vcpu_thread_rules()?, Thread::Vmm => vmm_thread_rules()?, }; @@ -473,6 +497,7 @@ fn get_seccomp_filter_trap(thread_type: Thread) -> Result fn get_seccomp_filter_log(thread_type: Thread) -> Result { let rules = match thread_type { Thread::Api => api_thread_rules()?, + Thread::SignalHandler => signal_handler_thread_rules()?, Thread::Vcpu => vcpu_thread_rules()?, Thread::Vmm => vmm_thread_rules()?, }; diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index 8d7f6ab6a..1377a0fea 100644 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -33,6 +33,7 @@ use crate::cpu; use crate::device_manager::{self, get_win_size, Console, DeviceManager, DeviceManagerError}; use crate::memory_manager::{Error as MemoryManagerError, MemoryManager}; use crate::migration::{get_vm_snapshot, url_to_path, VM_SNAPSHOT_FILE}; +use crate::seccomp_filters::{get_seccomp_filter, Thread}; use crate::{ PciDeviceInfo, CPU_MANAGER_SNAPSHOT_ID, DEVICE_MANAGER_SNAPSHOT_ID, MEMORY_MANAGER_SNAPSHOT_ID, }; @@ -47,7 +48,7 @@ use linux_loader::loader::elf::Error::InvalidElfMagicNumber; #[cfg(target_arch = "x86_64")] use linux_loader::loader::elf::PvhBootCapability::PvhEntryPresent; use linux_loader::loader::KernelLoader; -use seccomp::SeccompAction; +use seccomp::{SeccompAction, SeccompFilter}; use signal_hook::{iterator::Signals, SIGINT, SIGTERM, SIGWINCH}; use std::collections::{BTreeMap, HashMap}; use std::convert::TryInto; @@ -202,6 +203,12 @@ pub enum Error { /// Invalid configuration for NUMA. InvalidNumaConfig, + + /// Cannot create seccomp filter + CreateSeccompFilter(seccomp::SeccompError), + + /// Cannot apply seccomp filter + ApplySeccompFilter(seccomp::Error), } pub type Result = result::Result; @@ -288,6 +295,7 @@ pub struct Vm { saved_clock: Option, #[cfg(feature = "acpi")] numa_nodes: NumaNodes, + seccomp_action: SeccompAction, } impl Vm { @@ -365,6 +373,7 @@ impl Vm { saved_clock: _saved_clock, #[cfg(feature = "acpi")] numa_nodes, + seccomp_action: seccomp_action.clone(), }) } @@ -1237,10 +1246,22 @@ impl Vm { self.signals = Some(signals.clone()); let on_tty = self.on_tty; + let signal_handler_seccomp_filter = + get_seccomp_filter(&self.seccomp_action, Thread::SignalHandler) + .map_err(Error::CreateSeccompFilter)?; self.threads.push( thread::Builder::new() .name("signal_handler".to_string()) - .spawn(move || Vm::os_signal_handler(signals, console, on_tty)) + .spawn(move || { + if let Err(e) = SeccompFilter::apply(signal_handler_seccomp_filter) + .map_err(Error::ApplySeccompFilter) + { + error!("Error applying seccomp filter: {:?}", e); + return; + } + + Vm::os_signal_handler(signals, console, on_tty); + }) .map_err(Error::SignalHandlerSpawn)?, ); } @@ -1461,10 +1482,29 @@ impl Snapshottable for Vm { self.signals = Some(signals.clone()); let on_tty = self.on_tty; + let signal_handler_seccomp_filter = + get_seccomp_filter(&self.seccomp_action, Thread::SignalHandler).map_err( + |e| { + MigratableError::Restore(anyhow!( + "Could not create seccomp filter: {:#?}", + Error::CreateSeccompFilter(e) + )) + }, + )?; + self.threads.push( thread::Builder::new() .name("signal_handler".to_string()) - .spawn(move || Vm::os_signal_handler(signals, console, on_tty)) + .spawn(move || { + if let Err(e) = SeccompFilter::apply(signal_handler_seccomp_filter) + .map_err(Error::ApplySeccompFilter) + { + error!("Error applying seccomp filter: {:?}", e); + return; + } + + Vm::os_signal_handler(signals, console, on_tty) + }) .map_err(|e| { MigratableError::Restore(anyhow!( "Could not start console signal thread: {:#?}",