diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index 06adcf8cf..d30d4a220 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -2534,6 +2534,7 @@ impl DeviceManager { self.exit_evt .try_clone() .map_err(DeviceManagerError::EventFd)?, + &self.seccomp_action, ) .map_err(DeviceManagerError::SpawnSerialManager)?; Some(Arc::new(serial_manager)) diff --git a/vmm/src/seccomp_filters.rs b/vmm/src/seccomp_filters.rs index b08e8303b..0aeb6f979 100644 --- a/vmm/src/seccomp_filters.rs +++ b/vmm/src/seccomp_filters.rs @@ -39,6 +39,7 @@ pub enum Thread { Vcpu, Vmm, PtyForeground, + SerialManager, } /// Shorthand for chaining `SeccompCondition`s with the `and` operator in a `SeccompRule`. @@ -1031,6 +1032,33 @@ fn event_monitor_thread_rules() -> Result)>, BackendE ]) } +fn serial_manager_thread_rules() -> Result)>, BackendError> { + Ok(vec![ + (libc::SYS_accept4, vec![]), + (libc::SYS_clock_nanosleep, vec![]), + (libc::SYS_clock_gettime, vec![]), + (libc::SYS_close, vec![]), + (libc::SYS_epoll_ctl, vec![]), + (libc::SYS_epoll_pwait, vec![]), + #[cfg(target_arch = "x86_64")] + (libc::SYS_epoll_wait, vec![]), + (libc::SYS_exit, vec![]), + (libc::SYS_fcntl, vec![]), + (libc::SYS_futex, vec![]), + (libc::SYS_madvise, vec![]), + (libc::SYS_mmap, vec![]), + (libc::SYS_munmap, vec![]), + (libc::SYS_nanosleep, vec![]), + (libc::SYS_read, vec![]), + (libc::SYS_recvfrom, vec![]), + (libc::SYS_rt_sigprocmask, vec![]), + (libc::SYS_rt_sigreturn, vec![]), + (libc::SYS_shutdown, vec![]), + (libc::SYS_sigaltstack, vec![]), + (libc::SYS_write, vec![]), + ]) +} + fn get_seccomp_rules( thread_type: Thread, hypervisor_type: Option, @@ -1040,6 +1068,7 @@ fn get_seccomp_rules( #[cfg(feature = "dbus_api")] Thread::DBusApi => Ok(dbus_api_thread_rules()?), Thread::EventMonitor => Ok(event_monitor_thread_rules()?), + Thread::SerialManager => Ok(serial_manager_thread_rules()?), Thread::SignalHandler => Ok(signal_handler_thread_rules()?), Thread::Vcpu => Ok(vcpu_thread_rules( hypervisor_type.expect("hypervisor_type is required for Vcpu threads"), diff --git a/vmm/src/serial_manager.rs b/vmm/src/serial_manager.rs index 27f359bec..ce2eddc43 100644 --- a/vmm/src/serial_manager.rs +++ b/vmm/src/serial_manager.rs @@ -21,11 +21,13 @@ use devices::legacy::Pl011; use devices::legacy::Serial; use libc::EFD_NONBLOCK; use log::{error, info, warn}; +use seccompiler::{SeccompAction, apply_filter}; use serial_buffer::SerialBuffer; use thiserror::Error; use vmm_sys_util::eventfd::EventFd; use crate::console_devices::ConsoleTransport; +use crate::seccomp_filters::{Thread, get_seccomp_filter}; #[derive(Debug, Error)] pub enum Error { @@ -84,6 +86,14 @@ pub enum Error { /// Cannot duplicate file descriptor #[error("Error duplicating file descriptor")] DupFd(#[source] io::Error), + + /// Cannot create seccomp filter. + #[error("Error creating seccomp filter")] + CreateSeccompFilter(seccompiler::Error), + + /// Cannot apply seccomp filter. + #[error("Error applying seccomp filter")] + ApplySeccompFilter(seccompiler::Error), } pub type Result = result::Result; @@ -250,13 +260,20 @@ impl SerialManager { Ok(()) } - pub fn start_thread(&mut self, exit_evt: EventFd) -> Result<()> { + pub fn start_thread( + &mut self, + exit_evt: EventFd, + seccomp_action: &SeccompAction, + ) -> Result<()> { // Don't allow this to be run if the handle exists if self.handle.is_some() { warn!("Tried to start multiple SerialManager threads, ignoring"); return Ok(()); } + let seccomp_filter = get_seccomp_filter(seccomp_action, Thread::SerialManager, None) + .map_err(Error::CreateSeccompFilter)?; + let epoll_fd = self.epoll_fd.try_clone().map_err(Error::Epoll)?; let transport = self.transport.clone(); let serial = self.serial.clone(); @@ -275,6 +292,11 @@ impl SerialManager { .name("serial-manager".to_string()) .spawn(move || { std::panic::catch_unwind(AssertUnwindSafe(move || { + // Apply seccomp filter for serial manager thread. + if !seccomp_filter.is_empty() { + apply_filter(&seccomp_filter).map_err(Error::ApplySeccompFilter)?; + } + let mut events = [epoll::Event::new(epoll::Events::empty(), 0); EPOLL_EVENTS_LEN];