From a426221167c239faeb3211cb57aaf86342920ad8 Mon Sep 17 00:00:00 2001 From: Bo Chen Date: Tue, 4 Aug 2020 10:46:49 -0700 Subject: [PATCH] virtio-devices: seccomp: Add seccomp filters for rng thread This patch enables the seccomp filters for the rng worker thread. Partially fixes: #925 Signed-off-by: Bo Chen --- virtio-devices/src/lib.rs | 1 + virtio-devices/src/rng.rs | 22 ++++++++++++++++++++-- virtio-devices/src/seccomp_filters.rs | 27 +++++++++++++++++++++++++++ vmm/src/device_manager.rs | 9 +++++++-- 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/virtio-devices/src/lib.rs b/virtio-devices/src/lib.rs index 886e041d5..3ba0305f6 100644 --- a/virtio-devices/src/lib.rs +++ b/virtio-devices/src/lib.rs @@ -129,4 +129,5 @@ pub enum Error { EpollHander(String), NoMemoryConfigured, NetQueuePair(::net_util::NetQueuePairError), + ApplySeccompFilter(seccomp::Error), } diff --git a/virtio-devices/src/rng.rs b/virtio-devices/src/rng.rs index 4b2896a47..97af3777f 100644 --- a/virtio-devices/src/rng.rs +++ b/virtio-devices/src/rng.rs @@ -8,9 +8,11 @@ use super::{ VirtioDevice, VirtioDeviceType, EPOLL_HELPER_EVENT_LAST, VIRTIO_F_IOMMU_PLATFORM, VIRTIO_F_VERSION_1, }; +use crate::seccomp_filters::{get_seccomp_filter, Thread}; use crate::{VirtioInterrupt, VirtioInterruptType}; use anyhow::anyhow; use libc::EFD_NONBLOCK; +use seccomp::{SeccompAction, SeccompFilter}; use std::fs::File; use std::io; use std::os::unix::io::AsRawFd; @@ -130,6 +132,7 @@ pub struct Rng { interrupt_cb: Option>, epoll_threads: Option>>>, paused: Arc, + seccomp_action: SeccompAction, } #[derive(Serialize, Deserialize)] @@ -141,7 +144,12 @@ pub struct RngState { impl Rng { /// Create a new virtio rng device that gets random data from /dev/urandom. - pub fn new(id: String, path: &str, iommu: bool) -> io::Result { + pub fn new( + id: String, + path: &str, + iommu: bool, + seccomp_action: SeccompAction, + ) -> io::Result { let random_file = File::open(path)?; let mut avail_features = 1u64 << VIRTIO_F_VERSION_1; @@ -160,6 +168,7 @@ impl Rng { interrupt_cb: None, epoll_threads: None, paused: Arc::new(AtomicBool::new(false)), + seccomp_action, }) } @@ -279,9 +288,18 @@ impl VirtioDevice for Rng { let paused = self.paused.clone(); let mut epoll_threads = Vec::new(); + // Retrieve seccomp filter for virtio_rng thread + let virtio_rng_seccomp_filter = + get_seccomp_filter(&self.seccomp_action, Thread::VirtioRng) + .map_err(ActivateError::CreateSeccompFilter)?; thread::Builder::new() .name("virtio_rng".to_string()) - .spawn(move || handler.run(paused)) + .spawn(move || { + SeccompFilter::apply(virtio_rng_seccomp_filter) + .map_err(DeviceError::ApplySeccompFilter)?; + + handler.run(paused) + }) .map(|thread| epoll_threads.push(thread)) .map_err(|e| { error!("failed to clone the virtio-rng epoll thread: {}", e); diff --git a/virtio-devices/src/seccomp_filters.rs b/virtio-devices/src/seccomp_filters.rs index ef6e2dfd1..7124b01b5 100644 --- a/virtio-devices/src/seccomp_filters.rs +++ b/virtio-devices/src/seccomp_filters.rs @@ -11,6 +11,7 @@ use std::convert::TryInto; pub enum Thread { VirtioBlk, + VirtioRng, } // The filter containing the allowed syscall rules required by the @@ -52,9 +53,34 @@ fn virtio_blk_thread_rules() -> Result, Error> { ]) } +fn virtio_rng_thread_rules() -> Result, Error> { + Ok(vec![ + allow_syscall(libc::SYS_close), + allow_syscall(libc::SYS_epoll_create1), + allow_syscall(libc::SYS_epoll_ctl), + allow_syscall(libc::SYS_epoll_pwait), + #[cfg(target_arch = "x86_64")] + allow_syscall(libc::SYS_epoll_wait), + allow_syscall(libc::SYS_exit), + allow_syscall(libc::SYS_futex), + allow_syscall(libc::SYS_madvise), + allow_syscall(libc::SYS_mmap), + allow_syscall(libc::SYS_mprotect), + allow_syscall(libc::SYS_munmap), + allow_syscall(libc::SYS_prctl), + allow_syscall(libc::SYS_read), + allow_syscall(libc::SYS_rt_sigprocmask), + allow_syscall(libc::SYS_sched_getaffinity), + allow_syscall(libc::SYS_set_robust_list), + allow_syscall(libc::SYS_sigaltstack), + allow_syscall(libc::SYS_write), + ]) +} + fn get_seccomp_filter_trap(thread_type: Thread) -> Result { let rules = match thread_type { Thread::VirtioBlk => virtio_blk_thread_rules()?, + Thread::VirtioRng => virtio_rng_thread_rules()?, }; Ok(SeccompFilter::new( @@ -66,6 +92,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::VirtioBlk => virtio_blk_thread_rules()?, + Thread::VirtioRng => virtio_rng_thread_rules()?, }; Ok(SeccompFilter::new( diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index a4867cd66..9a36d3ff8 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -1960,8 +1960,13 @@ impl DeviceManager { let id = String::from(RNG_DEVICE_NAME); let virtio_rng_device = Arc::new(Mutex::new( - virtio_devices::Rng::new(id.clone(), rng_path, rng_config.iommu) - .map_err(DeviceManagerError::CreateVirtioRng)?, + virtio_devices::Rng::new( + id.clone(), + rng_path, + rng_config.iommu, + self.seccomp_action.clone(), + ) + .map_err(DeviceManagerError::CreateVirtioRng)?, )); devices.push(( Arc::clone(&virtio_rng_device) as VirtioDeviceArc,