diff --git a/vmm/src/api/http.rs b/vmm/src/api/http.rs index b49bb1398..e6a6901ac 100644 --- a/vmm/src/api/http.rs +++ b/vmm/src/api/http.rs @@ -7,6 +7,7 @@ use crate::api::http_endpoint::{VmActionHandler, VmCreate, VmInfo, VmmPing, VmmS use crate::api::{ApiError, ApiRequest, VmAction}; use crate::seccomp_filters::{get_seccomp_filter, Thread}; use crate::{Error as VmmError, Result}; +use hypervisor::HypervisorType; use micro_http::{Body, HttpServer, MediaType, Method, Request, Response, StatusCode, Version}; use once_cell::sync::Lazy; use seccompiler::{apply_filter, SeccompAction}; @@ -278,10 +279,11 @@ fn start_http_thread( api_sender: Sender, seccomp_action: &SeccompAction, exit_evt: EventFd, + hypervisor_type: HypervisorType, ) -> Result>> { // Retrieve seccomp filter for API thread - let api_seccomp_filter = - get_seccomp_filter(seccomp_action, Thread::Api).map_err(VmmError::CreateSeccompFilter)?; + let api_seccomp_filter = get_seccomp_filter(seccomp_action, Thread::Api, hypervisor_type) + .map_err(VmmError::CreateSeccompFilter)?; thread::Builder::new() .name("http-server".to_string()) @@ -336,12 +338,20 @@ pub fn start_http_path_thread( api_sender: Sender, seccomp_action: &SeccompAction, exit_evt: EventFd, + hypervisor_type: HypervisorType, ) -> Result>> { let socket_path = PathBuf::from(path); let socket_fd = UnixListener::bind(socket_path).map_err(VmmError::CreateApiServerSocket)?; let server = HttpServer::new_from_fd(socket_fd.into_raw_fd()).map_err(VmmError::CreateApiServer)?; - start_http_thread(server, api_notifier, api_sender, seccomp_action, exit_evt) + start_http_thread( + server, + api_notifier, + api_sender, + seccomp_action, + exit_evt, + hypervisor_type, + ) } pub fn start_http_fd_thread( @@ -350,7 +360,15 @@ pub fn start_http_fd_thread( api_sender: Sender, seccomp_action: &SeccompAction, exit_evt: EventFd, + hypervisor_type: HypervisorType, ) -> Result>> { let server = HttpServer::new_from_fd(fd).map_err(VmmError::CreateApiServer)?; - start_http_thread(server, api_notifier, api_sender, seccomp_action, exit_evt) + start_http_thread( + server, + api_notifier, + api_sender, + seccomp_action, + exit_evt, + hypervisor_type, + ) } diff --git a/vmm/src/cpu.rs b/vmm/src/cpu.rs index 2865d9c46..5b84b50cf 100644 --- a/vmm/src/cpu.rs +++ b/vmm/src/cpu.rs @@ -46,7 +46,7 @@ use hypervisor::arch::x86::{SpecialRegisters, StandardRegisters}; use hypervisor::kvm::kvm_bindings; #[cfg(feature = "tdx")] use hypervisor::kvm::{TdxExitDetails, TdxExitStatus}; -use hypervisor::{CpuState, HypervisorCpuError, VmExit, VmOps}; +use hypervisor::{CpuState, HypervisorCpuError, HypervisorType, VmExit, VmOps}; use libc::{c_void, siginfo_t}; #[cfg(feature = "guest_debug")] use linux_loader::elf::Elf64_Nhdr; @@ -412,6 +412,7 @@ impl Snapshottable for Vcpu { } pub struct CpuManager { + hypervisor_type: HypervisorType, config: CpusConfig, #[cfg_attr(target_arch = "aarch64", allow(dead_code))] interrupt_controller: Option>>, @@ -589,6 +590,7 @@ impl CpuManager { let guest_memory = memory_manager.lock().unwrap().guest_memory(); let mut vcpu_states = Vec::with_capacity(usize::from(config.max_vcpus)); vcpu_states.resize_with(usize::from(config.max_vcpus), VcpuState::default); + let hypervisor_type = hypervisor.hypervisor_type(); #[cfg(target_arch = "x86_64")] let sgx_epc_sections = memory_manager @@ -688,6 +690,7 @@ impl CpuManager { }; let cpu_manager = Arc::new(Mutex::new(CpuManager { + hypervisor_type, config: config.clone(), interrupt_controller: device_manager.interrupt_controller().clone(), vm_memory: guest_memory, @@ -836,8 +839,9 @@ impl CpuManager { }); // Retrieve seccomp filter for vcpu thread - let vcpu_seccomp_filter = get_seccomp_filter(&self.seccomp_action, Thread::Vcpu) - .map_err(Error::CreateSeccompFilter)?; + let vcpu_seccomp_filter = + get_seccomp_filter(&self.seccomp_action, Thread::Vcpu, self.hypervisor_type) + .map_err(Error::CreateSeccompFilter)?; #[cfg(target_arch = "x86_64")] let interrupt_controller_clone = self.interrupt_controller.as_ref().cloned(); diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index b2d405893..09f9a2231 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -50,7 +50,7 @@ use devices::legacy::Serial; use devices::{ interrupt_controller, interrupt_controller::InterruptController, AcpiNotificationFlags, }; -use hypervisor::{HypervisorVmError, IoEventAddress}; +use hypervisor::{HypervisorType, HypervisorVmError, IoEventAddress}; use libc::{ cfmakeraw, isatty, tcgetattr, tcsetattr, termios, MAP_NORESERVE, MAP_PRIVATE, MAP_SHARED, O_TMPFILE, PROT_READ, PROT_WRITE, TCSANOW, @@ -807,6 +807,9 @@ struct MetaVirtioDevice { } pub struct DeviceManager { + // The underlying hypervisor + hypervisor_type: HypervisorType, + // Manage address space related to devices address_manager: Arc, @@ -945,6 +948,7 @@ pub struct DeviceManager { impl DeviceManager { #[allow(clippy::too_many_arguments)] pub fn new( + hypervisor_type: HypervisorType, vm: Arc, config: Arc>, memory_manager: Arc>, @@ -1035,6 +1039,7 @@ impl DeviceManager { } let device_manager = DeviceManager { + hypervisor_type, address_manager: Arc::clone(&address_manager), console: Arc::new(Console::default()), interrupt_controller: None, @@ -1803,8 +1808,12 @@ impl DeviceManager { } fn listen_for_sigwinch_on_tty(&mut self, pty: &File) -> std::io::Result<()> { - let seccomp_filter = - get_seccomp_filter(&self.seccomp_action, Thread::PtyForeground).unwrap(); + let seccomp_filter = get_seccomp_filter( + &self.seccomp_action, + Thread::PtyForeground, + self.hypervisor_type, + ) + .unwrap(); match start_sigwinch_listener(seccomp_filter, pty) { Ok(pipe) => { diff --git a/vmm/src/lib.rs b/vmm/src/lib.rs index 8d415afbe..1fbf5c41c 100644 --- a/vmm/src/lib.rs +++ b/vmm/src/lib.rs @@ -280,10 +280,11 @@ pub fn start_vmm_thread( let gdb_vm_debug_event = vm_debug_event.try_clone().map_err(Error::EventFdClone)?; let http_api_event = api_event.try_clone().map_err(Error::EventFdClone)?; + let hypervisor_type = hypervisor.hypervisor_type(); // Retrieve seccomp filter - let vmm_seccomp_filter = - get_seccomp_filter(seccomp_action, Thread::Vmm).map_err(Error::CreateSeccompFilter)?; + let vmm_seccomp_filter = get_seccomp_filter(seccomp_action, Thread::Vmm, hypervisor_type) + .map_err(Error::CreateSeccompFilter)?; let vmm_seccomp_action = seccomp_action.clone(); let exit_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::EventFdCreate)?; @@ -328,6 +329,7 @@ pub fn start_vmm_thread( api_sender, seccomp_action, exit_evt, + hypervisor_type, )?; } else if let Some(http_fd) = http_fd { api::start_http_fd_thread( @@ -336,6 +338,7 @@ pub fn start_vmm_thread( api_sender, seccomp_action, exit_evt, + hypervisor_type, )?; } @@ -413,9 +416,12 @@ impl Vmm { let exit_evt = self.exit_evt.try_clone().map_err(Error::EventFdClone)?; let on_tty = unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0; - let signal_handler_seccomp_filter = - get_seccomp_filter(&self.seccomp_action, Thread::SignalHandler) - .map_err(Error::CreateSeccompFilter)?; + let signal_handler_seccomp_filter = get_seccomp_filter( + &self.seccomp_action, + Thread::SignalHandler, + self.hypervisor.hypervisor_type(), + ) + .map_err(Error::CreateSeccompFilter)?; self.threads.push( thread::Builder::new() .name("vmm_signal_handler".to_string()) diff --git a/vmm/src/seccomp_filters.rs b/vmm/src/seccomp_filters.rs index 10c290035..2b94615a7 100644 --- a/vmm/src/seccomp_filters.rs +++ b/vmm/src/seccomp_filters.rs @@ -4,6 +4,7 @@ // // SPDX-License-Identifier: Apache-2.0 +use hypervisor::HypervisorType; use seccompiler::{ BackendError, BpfProgram, Error, SeccompAction, SeccompCmpArgLen as ArgLen, SeccompCmpOp::Eq, SeccompCondition as Cond, SeccompFilter, SeccompRule, @@ -226,17 +227,22 @@ fn create_vmm_ioctl_seccomp_rule_common_kvm() -> Result, Backen ]) } -fn create_vmm_ioctl_seccomp_rule_hypervisor() -> Result, BackendError> { - #[cfg(feature = "kvm")] - let rules = create_vmm_ioctl_seccomp_rule_common_kvm(); - - #[cfg(feature = "mshv")] - let rules = create_vmm_ioctl_seccomp_rule_common_mshv(); - - rules +fn create_vmm_ioctl_seccomp_rule_hypervisor( + hypervisor_type: HypervisorType, +) -> Result, BackendError> { + match hypervisor_type { + #[cfg(feature = "kvm")] + HypervisorType::Kvm => create_vmm_ioctl_seccomp_rule_common_kvm(), + #[cfg(feature = "mshv")] + HypervisorType::Mshv => create_vmm_ioctl_seccomp_rule_common_mshv(), + #[allow(unreachable_patterns)] + _ => panic!("Invalid hypervisor {:?}", hypervisor_type), + } } -fn create_vmm_ioctl_seccomp_rule_common() -> Result, BackendError> { +fn create_vmm_ioctl_seccomp_rule_common( + hypervisor_type: HypervisorType, +) -> Result, BackendError> { let mut common_rules = or![ and![Cond::new(1, ArgLen::Dword, Eq, BLKSSZGET)?], and![Cond::new(1, ArgLen::Dword, Eq, BLKPBSZGET)?], @@ -308,7 +314,7 @@ fn create_vmm_ioctl_seccomp_rule_common() -> Result, BackendErr and![Cond::new(1, ArgLen::Dword, Eq, VHOST_VDPA_GET_IOVA_RANGE)?], ]; - let hypervisor_rules = create_vmm_ioctl_seccomp_rule_hypervisor()?; + let hypervisor_rules = create_vmm_ioctl_seccomp_rule_hypervisor(hypervisor_type)?; common_rules.extend(hypervisor_rules); @@ -341,7 +347,7 @@ fn create_vmm_ioctl_seccomp_rule_kvm() -> Result, BackendError> const KVM_SET_GUEST_DEBUG: u64 = 0x4048_ae9b; const KVM_TRANSLATE: u64 = 0xc018_ae85; - let common_rules = create_vmm_ioctl_seccomp_rule_common()?; + let common_rules = create_vmm_ioctl_seccomp_rule_common(HypervisorType::Kvm)?; let mut arch_rules = or![ and![Cond::new(1, ArgLen::Dword, Eq, KVM_CREATE_PIT2)?], and![Cond::new(1, ArgLen::Dword, Eq, KVM_GET_CLOCK,)?], @@ -377,7 +383,7 @@ fn create_vmm_ioctl_seccomp_rule_kvm() -> Result, BackendError> const KVM_ARM_PREFERRED_TARGET: u64 = 0x8020_aeaf; const KVM_ARM_VCPU_INIT: u64 = 0x4020_aeae; - let common_rules = create_vmm_ioctl_seccomp_rule_common()?; + let common_rules = create_vmm_ioctl_seccomp_rule_common(HypervisorType::Kvm)?; let mut arch_rules = or![ and![Cond::new(1, ArgLen::Dword, Eq, KVM_ARM_PREFERRED_TARGET,)?], and![Cond::new(1, ArgLen::Dword, Eq, KVM_ARM_VCPU_INIT,)?], @@ -389,17 +395,20 @@ fn create_vmm_ioctl_seccomp_rule_kvm() -> Result, BackendError> #[cfg(all(target_arch = "x86_64", feature = "mshv"))] fn create_vmm_ioctl_seccomp_rule_mshv() -> Result, BackendError> { - create_vmm_ioctl_seccomp_rule_common() + create_vmm_ioctl_seccomp_rule_common(HypervisorType::Mshv) } -fn create_vmm_ioctl_seccomp_rule() -> Result, BackendError> { - #[cfg(feature = "kvm")] - let rules = create_vmm_ioctl_seccomp_rule_kvm(); - - #[cfg(feature = "mshv")] - let rules = create_vmm_ioctl_seccomp_rule_mshv(); - - rules +fn create_vmm_ioctl_seccomp_rule( + hypervisor_type: HypervisorType, +) -> Result, BackendError> { + match hypervisor_type { + #[cfg(feature = "kvm")] + HypervisorType::Kvm => create_vmm_ioctl_seccomp_rule_kvm(), + #[cfg(feature = "mshv")] + HypervisorType::Mshv => create_vmm_ioctl_seccomp_rule_mshv(), + #[allow(unreachable_patterns)] + _ => panic!("Invalid hypervisor {:?}", hypervisor_type), + } } fn create_api_ioctl_seccomp_rule() -> Result, BackendError> { @@ -465,7 +474,9 @@ fn pty_foreground_thread_rules() -> Result)>, Backend // The filter containing the white listed syscall rules required by the VMM to // function. -fn vmm_thread_rules() -> Result)>, BackendError> { +fn vmm_thread_rules( + hypervisor_type: HypervisorType, +) -> Result)>, BackendError> { Ok(vec![ (libc::SYS_accept4, vec![]), #[cfg(target_arch = "x86_64")] @@ -506,7 +517,10 @@ fn vmm_thread_rules() -> Result)>, BackendError> { (libc::SYS_gettid, vec![]), (libc::SYS_gettimeofday, vec![]), (libc::SYS_getuid, vec![]), - (libc::SYS_ioctl, create_vmm_ioctl_seccomp_rule()?), + ( + libc::SYS_ioctl, + create_vmm_ioctl_seccomp_rule(hypervisor_type)?, + ), (libc::SYS_io_uring_enter, vec![]), (libc::SYS_io_uring_setup, vec![]), (libc::SYS_io_uring_register, vec![]), @@ -619,17 +633,22 @@ fn create_vcpu_ioctl_seccomp_rule_mshv() -> Result, BackendErro ]) } -fn create_vcpu_ioctl_seccomp_rule_hypervisor() -> Result, BackendError> { - #[cfg(feature = "kvm")] - let rules = create_vcpu_ioctl_seccomp_rule_kvm(); - - #[cfg(feature = "mshv")] - let rules = create_vcpu_ioctl_seccomp_rule_mshv(); - - rules +fn create_vcpu_ioctl_seccomp_rule_hypervisor( + hypervisor_type: HypervisorType, +) -> Result, BackendError> { + match hypervisor_type { + #[cfg(feature = "kvm")] + HypervisorType::Kvm => create_vcpu_ioctl_seccomp_rule_kvm(), + #[cfg(feature = "mshv")] + HypervisorType::Mshv => create_vcpu_ioctl_seccomp_rule_mshv(), + #[allow(unreachable_patterns)] + _ => panic!("Invalid hypervisor {:?}", hypervisor_type), + } } -fn create_vcpu_ioctl_seccomp_rule() -> Result, BackendError> { +fn create_vcpu_ioctl_seccomp_rule( + hypervisor_type: HypervisorType, +) -> Result, BackendError> { let mut rules = or![ and![Cond::new(1, ArgLen::Dword, Eq, VFIO_DEVICE_SET_IRQS)?], and![Cond::new(1, ArgLen::Dword, Eq, VFIO_GROUP_UNSET_CONTAINER)?], @@ -645,14 +664,16 @@ fn create_vcpu_ioctl_seccomp_rule() -> Result, BackendError> { )?], ]; - let hypervisor_rules = create_vcpu_ioctl_seccomp_rule_hypervisor()?; + let hypervisor_rules = create_vcpu_ioctl_seccomp_rule_hypervisor(hypervisor_type)?; rules.extend(hypervisor_rules); Ok(rules) } -fn vcpu_thread_rules() -> Result)>, BackendError> { +fn vcpu_thread_rules( + hypervisor_type: HypervisorType, +) -> Result)>, BackendError> { Ok(vec![ (libc::SYS_brk, vec![]), (libc::SYS_clock_gettime, vec![]), @@ -665,7 +686,10 @@ fn vcpu_thread_rules() -> Result)>, BackendError> { (libc::SYS_futex, vec![]), (libc::SYS_getrandom, vec![]), (libc::SYS_getpid, vec![]), - (libc::SYS_ioctl, create_vcpu_ioctl_seccomp_rule()?), + ( + libc::SYS_ioctl, + create_vcpu_ioctl_seccomp_rule(hypervisor_type)?, + ), (libc::SYS_lseek, vec![]), (libc::SYS_madvise, vec![]), (libc::SYS_mmap, vec![]), @@ -727,12 +751,15 @@ fn api_thread_rules() -> Result)>, BackendError> { ]) } -fn get_seccomp_rules(thread_type: Thread) -> Result)>, BackendError> { +fn get_seccomp_rules( + thread_type: Thread, + hypervisor_type: HypervisorType, +) -> Result)>, BackendError> { match thread_type { Thread::Api => Ok(api_thread_rules()?), Thread::SignalHandler => Ok(signal_handler_thread_rules()?), - Thread::Vcpu => Ok(vcpu_thread_rules()?), - Thread::Vmm => Ok(vmm_thread_rules()?), + Thread::Vcpu => Ok(vcpu_thread_rules(hypervisor_type)?), + Thread::Vmm => Ok(vmm_thread_rules(hypervisor_type)?), Thread::PtyForeground => Ok(pty_foreground_thread_rules()?), } } @@ -741,11 +768,12 @@ fn get_seccomp_rules(thread_type: Thread) -> Result)> pub fn get_seccomp_filter( seccomp_action: &SeccompAction, thread_type: Thread, + hypervisor_type: HypervisorType, ) -> Result { match seccomp_action { SeccompAction::Allow => Ok(vec![]), SeccompAction::Log => SeccompFilter::new( - get_seccomp_rules(thread_type) + get_seccomp_rules(thread_type, hypervisor_type) .map_err(Error::Backend)? .into_iter() .collect(), @@ -756,7 +784,7 @@ pub fn get_seccomp_filter( .and_then(|filter| filter.try_into()) .map_err(Error::Backend), _ => SeccompFilter::new( - get_seccomp_rules(thread_type) + get_seccomp_rules(thread_type, hypervisor_type) .map_err(Error::Backend)? .into_iter() .collect(), diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index 28d37cd49..af6881ff0 100644 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -471,7 +471,6 @@ pub struct Vm { numa_nodes: NumaNodes, seccomp_action: SeccompAction, exit_evt: EventFd, - #[cfg(all(feature = "kvm", target_arch = "x86_64"))] hypervisor: Arc, stop_on_boot: bool, #[cfg(target_arch = "x86_64")] @@ -534,6 +533,7 @@ impl Vm { let stop_on_boot = false; let device_manager = DeviceManager::new( + hypervisor.hypervisor_type(), vm.clone(), config.clone(), memory_manager.clone(), @@ -617,7 +617,6 @@ impl Vm { numa_nodes, seccomp_action: seccomp_action.clone(), exit_evt, - #[cfg(all(feature = "kvm", target_arch = "x86_64"))] hypervisor, stop_on_boot, #[cfg(target_arch = "x86_64")] @@ -1969,9 +1968,12 @@ impl Vm { Ok(signals) => { self.signals = Some(signals.handle()); let exit_evt = self.exit_evt.try_clone().map_err(Error::EventFdClone)?; - let signal_handler_seccomp_filter = - get_seccomp_filter(&self.seccomp_action, Thread::SignalHandler) - .map_err(Error::CreateSeccompFilter)?; + let signal_handler_seccomp_filter = get_seccomp_filter( + &self.seccomp_action, + Thread::SignalHandler, + self.hypervisor.hypervisor_type(), + ) + .map_err(Error::CreateSeccompFilter)?; self.threads.push( thread::Builder::new() .name("vm_signal_handler".to_string())