virtio-devices: Use a common method for spawning virtio threads

Introduce a common solution for spawning the virtio threads which will
make it easier to add the panic handling.

During this effort I discovered that there were no seccomp filters
registered for the vhost-user-net thread nor the vhost-user-block
thread. This change also incorporates basic seccomp filters for those as
part of the refactoring.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
Rob Bradford 2021-09-03 11:43:30 +01:00
parent 4737679661
commit 54e523c302
17 changed files with 311 additions and 316 deletions

View File

@ -16,11 +16,12 @@ use super::{
ActivateError, ActivateResult, EpollHelper, EpollHelperError, EpollHelperHandler, Queue, ActivateError, ActivateResult, EpollHelper, EpollHelperError, EpollHelperHandler, Queue,
VirtioCommon, VirtioDevice, VirtioDeviceType, EPOLL_HELPER_EVENT_LAST, VIRTIO_F_VERSION_1, VirtioCommon, VirtioDevice, VirtioDeviceType, EPOLL_HELPER_EVENT_LAST, VIRTIO_F_VERSION_1,
}; };
use crate::seccomp_filters::{get_seccomp_filter, Thread}; use crate::seccomp_filters::Thread;
use crate::thread_helper::spawn_virtio_thread;
use crate::GuestMemoryMmap; use crate::GuestMemoryMmap;
use crate::{VirtioInterrupt, VirtioInterruptType}; use crate::{VirtioInterrupt, VirtioInterruptType};
use libc::EFD_NONBLOCK; use libc::EFD_NONBLOCK;
use seccompiler::{apply_filter, SeccompAction}; use seccompiler::SeccompAction;
use std::io; use std::io;
use std::mem::size_of; use std::mem::size_of;
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
@ -28,7 +29,6 @@ use std::result;
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::sync::mpsc; use std::sync::mpsc;
use std::sync::{Arc, Barrier, Mutex}; use std::sync::{Arc, Barrier, Mutex};
use std::thread;
use vm_memory::GuestMemory; use vm_memory::GuestMemory;
use vm_memory::{ use vm_memory::{
Address, ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemoryAtomic, Address, ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemoryAtomic,
@ -460,27 +460,18 @@ impl VirtioDevice for Balloon {
let paused = self.common.paused.clone(); let paused = self.common.paused.clone();
let paused_sync = self.common.paused_sync.clone(); let paused_sync = self.common.paused_sync.clone();
let mut epoll_threads = Vec::new(); let mut epoll_threads = Vec::new();
let virtio_balloon_seccomp_filter =
get_seccomp_filter(&self.seccomp_action, Thread::VirtioBalloon) spawn_virtio_thread(
.map_err(ActivateError::CreateSeccompFilter)?; &self.id,
thread::Builder::new() &self.seccomp_action,
.name(self.id.clone()) Thread::VirtioBalloon,
.spawn(move || { &mut epoll_threads,
if !virtio_balloon_seccomp_filter.is_empty() { move || {
if let Err(e) = apply_filter(&virtio_balloon_seccomp_filter) {
error!("Error applying seccomp filter: {:?}", e);
return;
}
}
if let Err(e) = handler.run(paused, paused_sync.unwrap()) { if let Err(e) = handler.run(paused, paused_sync.unwrap()) {
error!("Error running worker: {:?}", e); error!("Error running worker: {:?}", e);
} }
}) },
.map(|thread| epoll_threads.push(thread)) )?;
.map_err(|e| {
error!("failed to clone virtio-balloon epoll thread: {}", e);
ActivateError::BadActivate
})?;
self.common.epoll_threads = Some(epoll_threads); self.common.epoll_threads = Some(epoll_threads);
event!("virtio-device", "activated", "id", &self.id); event!("virtio-device", "activated", "id", &self.id);

View File

@ -14,7 +14,8 @@ use super::{
RateLimiterConfig, VirtioCommon, VirtioDevice, VirtioDeviceType, VirtioInterruptType, RateLimiterConfig, VirtioCommon, VirtioDevice, VirtioDeviceType, VirtioInterruptType,
EPOLL_HELPER_EVENT_LAST, EPOLL_HELPER_EVENT_LAST,
}; };
use crate::seccomp_filters::{get_seccomp_filter, Thread}; use crate::seccomp_filters::Thread;
use crate::thread_helper::spawn_virtio_thread;
use crate::GuestMemoryMmap; use crate::GuestMemoryMmap;
use crate::VirtioInterrupt; use crate::VirtioInterrupt;
use block_util::{ use block_util::{
@ -22,7 +23,7 @@ use block_util::{
RequestType, VirtioBlockConfig, RequestType, VirtioBlockConfig,
}; };
use rate_limiter::{RateLimiter, TokenType}; use rate_limiter::{RateLimiter, TokenType};
use seccompiler::{apply_filter, SeccompAction}; use seccompiler::SeccompAction;
use std::io; use std::io;
use std::num::Wrapping; use std::num::Wrapping;
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
@ -30,7 +31,6 @@ use std::path::PathBuf;
use std::result; use std::result;
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::sync::{Arc, Barrier}; use std::sync::{Arc, Barrier};
use std::thread;
use std::{collections::HashMap, convert::TryInto}; use std::{collections::HashMap, convert::TryInto};
use versionize::{VersionMap, Versionize, VersionizeResult}; use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize; use versionize_derive::Versionize;
@ -588,29 +588,17 @@ impl VirtioDevice for Block {
let paused = self.common.paused.clone(); let paused = self.common.paused.clone();
let paused_sync = self.common.paused_sync.clone(); let paused_sync = self.common.paused_sync.clone();
// Retrieve seccomp filter for virtio_block thread spawn_virtio_thread(
let virtio_block_seccomp_filter = &format!("{}_q{}", self.id.clone(), i),
get_seccomp_filter(&self.seccomp_action, Thread::VirtioBlock) &self.seccomp_action,
.map_err(ActivateError::CreateSeccompFilter)?; Thread::VirtioBlock,
&mut epoll_threads,
thread::Builder::new() move || {
.name(format!("{}_q{}", self.id.clone(), i))
.spawn(move || {
if !virtio_block_seccomp_filter.is_empty() {
if let Err(e) = apply_filter(&virtio_block_seccomp_filter) {
error!("Error applying seccomp filter: {:?}", e);
return;
}
}
if let Err(e) = handler.run(paused, paused_sync.unwrap()) { if let Err(e) = handler.run(paused, paused_sync.unwrap()) {
error!("Error running worker: {:?}", e); error!("Error running worker: {:?}", e);
} }
}) },
.map(|thread| epoll_threads.push(thread)) )?;
.map_err(|e| {
error!("failed to clone the virtio-block epoll thread: {}", e);
ActivateError::BadActivate
})?;
} }
self.common.epoll_threads = Some(epoll_threads); self.common.epoll_threads = Some(epoll_threads);

View File

@ -3,15 +3,16 @@
use super::Error as DeviceError; use super::Error as DeviceError;
use super::{ use super::{
ActivateError, ActivateResult, EpollHelper, EpollHelperError, EpollHelperHandler, Queue, ActivateResult, EpollHelper, EpollHelperError, EpollHelperHandler, Queue, VirtioCommon,
VirtioCommon, VirtioDevice, VirtioDeviceType, VirtioInterruptType, EPOLL_HELPER_EVENT_LAST, VirtioDevice, VirtioDeviceType, VirtioInterruptType, EPOLL_HELPER_EVENT_LAST,
VIRTIO_F_IOMMU_PLATFORM, VIRTIO_F_VERSION_1, VIRTIO_F_IOMMU_PLATFORM, VIRTIO_F_VERSION_1,
}; };
use crate::seccomp_filters::{get_seccomp_filter, Thread}; use crate::seccomp_filters::Thread;
use crate::thread_helper::spawn_virtio_thread;
use crate::GuestMemoryMmap; use crate::GuestMemoryMmap;
use crate::VirtioInterrupt; use crate::VirtioInterrupt;
use libc::EFD_NONBLOCK; use libc::EFD_NONBLOCK;
use seccompiler::{apply_filter, SeccompAction}; use seccompiler::SeccompAction;
use std::cmp; use std::cmp;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::fs::File; use std::fs::File;
@ -21,7 +22,6 @@ use std::os::unix::io::AsRawFd;
use std::result; use std::result;
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::sync::{Arc, Barrier, Mutex}; use std::sync::{Arc, Barrier, Mutex};
use std::thread;
use versionize::{VersionMap, Versionize, VersionizeResult}; use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize; use versionize_derive::Versionize;
use vm_memory::{ByteValued, Bytes, GuestAddressSpace, GuestMemoryAtomic}; use vm_memory::{ByteValued, Bytes, GuestAddressSpace, GuestMemoryAtomic};
@ -467,28 +467,18 @@ impl VirtioDevice for Console {
let paused = self.common.paused.clone(); let paused = self.common.paused.clone();
let paused_sync = self.common.paused_sync.clone(); let paused_sync = self.common.paused_sync.clone();
let mut epoll_threads = Vec::new(); let mut epoll_threads = Vec::new();
// Retrieve seccomp filter for virtio_console thread
let virtio_console_seccomp_filter = spawn_virtio_thread(
get_seccomp_filter(&self.seccomp_action, Thread::VirtioConsole) &self.id,
.map_err(ActivateError::CreateSeccompFilter)?; &self.seccomp_action,
thread::Builder::new() Thread::VirtioConsole,
.name(self.id.clone()) &mut epoll_threads,
.spawn(move || { move || {
if !virtio_console_seccomp_filter.is_empty() {
if let Err(e) = apply_filter(&virtio_console_seccomp_filter) {
error!("Error applying seccomp filter: {:?}", e);
return;
}
}
if let Err(e) = handler.run(paused, paused_sync.unwrap()) { if let Err(e) = handler.run(paused, paused_sync.unwrap()) {
error!("Error running worker: {:?}", e); error!("Error running worker: {:?}", e);
} }
}) },
.map(|thread| epoll_threads.push(thread)) )?;
.map_err(|e| {
error!("failed to clone the virtio-console epoll thread: {}", e);
ActivateError::BadActivate
})?;
self.common.epoll_threads = Some(epoll_threads); self.common.epoll_threads = Some(epoll_threads);

View File

@ -4,14 +4,14 @@
use super::Error as DeviceError; use super::Error as DeviceError;
use super::{ use super::{
ActivateError, ActivateResult, DescriptorChain, EpollHelper, EpollHelperError, ActivateResult, DescriptorChain, EpollHelper, EpollHelperError, EpollHelperHandler, Queue,
EpollHelperHandler, Queue, VirtioCommon, VirtioDevice, VirtioDeviceType, VirtioCommon, VirtioDevice, VirtioDeviceType, EPOLL_HELPER_EVENT_LAST, VIRTIO_F_VERSION_1,
EPOLL_HELPER_EVENT_LAST, VIRTIO_F_VERSION_1,
}; };
use crate::seccomp_filters::{get_seccomp_filter, Thread}; use crate::seccomp_filters::Thread;
use crate::thread_helper::spawn_virtio_thread;
use crate::GuestMemoryMmap; use crate::GuestMemoryMmap;
use crate::{DmaRemapping, VirtioInterrupt, VirtioInterruptType}; use crate::{DmaRemapping, VirtioInterrupt, VirtioInterruptType};
use seccompiler::{apply_filter, SeccompAction}; use seccompiler::SeccompAction;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::fmt::{self, Display}; use std::fmt::{self, Display};
use std::io; use std::io;
@ -21,7 +21,6 @@ use std::os::unix::io::AsRawFd;
use std::result; use std::result;
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
use std::sync::{Arc, Barrier, RwLock}; use std::sync::{Arc, Barrier, RwLock};
use std::thread;
use versionize::{VersionMap, Versionize, VersionizeResult}; use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize; use versionize_derive::Versionize;
use vm_device::dma_mapping::ExternalDmaMapping; use vm_device::dma_mapping::ExternalDmaMapping;
@ -843,29 +842,17 @@ impl VirtioDevice for Iommu {
let paused = self.common.paused.clone(); let paused = self.common.paused.clone();
let paused_sync = self.common.paused_sync.clone(); let paused_sync = self.common.paused_sync.clone();
let mut epoll_threads = Vec::new(); let mut epoll_threads = Vec::new();
// Retrieve seccomp filter for virtio_iommu thread spawn_virtio_thread(
let virtio_iommu_seccomp_filter = &self.id,
get_seccomp_filter(&self.seccomp_action, Thread::VirtioIommu) &self.seccomp_action,
.map_err(ActivateError::CreateSeccompFilter)?; Thread::VirtioIommu,
thread::Builder::new() &mut epoll_threads,
.name(self.id.clone()) move || {
.spawn(move || {
if !virtio_iommu_seccomp_filter.is_empty() {
if let Err(e) = apply_filter(&virtio_iommu_seccomp_filter) {
error!("Error applying seccomp filter: {:?}", e);
return;
}
}
if let Err(e) = handler.run(paused, paused_sync.unwrap()) { if let Err(e) = handler.run(paused, paused_sync.unwrap()) {
error!("Error running worker: {:?}", e); error!("Error running worker: {:?}", e);
} }
}) },
.map(|thread| epoll_threads.push(thread)) )?;
.map_err(|e| {
error!("failed to clone the virtio-iommu epoll thread: {}", e);
ActivateError::BadActivate
})?;
self.common.epoll_threads = Some(epoll_threads); self.common.epoll_threads = Some(epoll_threads);

View File

@ -32,6 +32,7 @@ pub mod net;
mod pmem; mod pmem;
mod rng; mod rng;
pub mod seccomp_filters; pub mod seccomp_filters;
mod thread_helper;
pub mod transport; pub mod transport;
pub mod vhost_user; pub mod vhost_user;
pub mod vsock; pub mod vsock;

View File

@ -18,12 +18,13 @@ use super::{
EpollHelperHandler, Queue, VirtioCommon, VirtioDevice, VirtioDeviceType, EpollHelperHandler, Queue, VirtioCommon, VirtioDevice, VirtioDeviceType,
EPOLL_HELPER_EVENT_LAST, VIRTIO_F_VERSION_1, EPOLL_HELPER_EVENT_LAST, VIRTIO_F_VERSION_1,
}; };
use crate::seccomp_filters::{get_seccomp_filter, Thread}; use crate::seccomp_filters::Thread;
use crate::thread_helper::spawn_virtio_thread;
use crate::{GuestMemoryMmap, GuestRegionMmap}; use crate::{GuestMemoryMmap, GuestRegionMmap};
use crate::{VirtioInterrupt, VirtioInterruptType}; use crate::{VirtioInterrupt, VirtioInterruptType};
use anyhow::anyhow; use anyhow::anyhow;
use libc::EFD_NONBLOCK; use libc::EFD_NONBLOCK;
use seccompiler::{apply_filter, SeccompAction}; use seccompiler::SeccompAction;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::io; use std::io;
use std::mem::size_of; use std::mem::size_of;
@ -32,7 +33,6 @@ use std::result;
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::sync::mpsc; use std::sync::mpsc;
use std::sync::{Arc, Barrier, Mutex}; use std::sync::{Arc, Barrier, Mutex};
use std::thread;
use vm_device::dma_mapping::ExternalDmaMapping; use vm_device::dma_mapping::ExternalDmaMapping;
use vm_memory::{ use vm_memory::{
Address, ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemoryAtomic, Address, ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemoryAtomic,
@ -955,27 +955,18 @@ impl VirtioDevice for Mem {
let paused = self.common.paused.clone(); let paused = self.common.paused.clone();
let paused_sync = self.common.paused_sync.clone(); let paused_sync = self.common.paused_sync.clone();
let mut epoll_threads = Vec::new(); let mut epoll_threads = Vec::new();
// Retrieve seccomp filter for virtio_mem thread
let virtio_mem_seccomp_filter = get_seccomp_filter(&self.seccomp_action, Thread::VirtioMem) spawn_virtio_thread(
.map_err(ActivateError::CreateSeccompFilter)?; &self.id,
thread::Builder::new() &self.seccomp_action,
.name(self.id.clone()) Thread::VirtioMem,
.spawn(move || { &mut epoll_threads,
if !virtio_mem_seccomp_filter.is_empty() { move || {
if let Err(e) = apply_filter(&virtio_mem_seccomp_filter) {
error!("Error applying seccomp filter: {:?}", e);
return;
}
}
if let Err(e) = handler.run(paused, paused_sync.unwrap()) { if let Err(e) = handler.run(paused, paused_sync.unwrap()) {
error!("Error running worker: {:?}", e); error!("Error running worker: {:?}", e);
} }
}) },
.map(|thread| epoll_threads.push(thread)) )?;
.map_err(|e| {
error!("failed to clone virtio-mem epoll thread: {}", e);
ActivateError::BadActivate
})?;
self.common.epoll_threads = Some(epoll_threads); self.common.epoll_threads = Some(epoll_threads);
event!("virtio-device", "activated", "id", &self.id); event!("virtio-device", "activated", "id", &self.id);

View File

@ -11,7 +11,8 @@ use super::{
RateLimiterConfig, VirtioCommon, VirtioDevice, VirtioDeviceType, VirtioInterruptType, RateLimiterConfig, VirtioCommon, VirtioDevice, VirtioDeviceType, VirtioInterruptType,
EPOLL_HELPER_EVENT_LAST, EPOLL_HELPER_EVENT_LAST,
}; };
use crate::seccomp_filters::{get_seccomp_filter, Thread}; use crate::seccomp_filters::Thread;
use crate::thread_helper::spawn_virtio_thread;
use crate::GuestMemoryMmap; use crate::GuestMemoryMmap;
use crate::VirtioInterrupt; use crate::VirtioInterrupt;
use net_util::CtrlQueue; use net_util::CtrlQueue;
@ -20,7 +21,7 @@ use net_util::{
virtio_features_to_tap_offload, MacAddr, NetCounters, NetQueuePair, OpenTapError, RxVirtio, virtio_features_to_tap_offload, MacAddr, NetCounters, NetQueuePair, OpenTapError, RxVirtio,
Tap, TapError, TxVirtio, VirtioNetConfig, Tap, TapError, TxVirtio, VirtioNetConfig,
}; };
use seccompiler::{apply_filter, SeccompAction}; use seccompiler::SeccompAction;
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
use std::num::Wrapping; use std::num::Wrapping;
use std::os::unix::io::{AsRawFd, RawFd}; use std::os::unix::io::{AsRawFd, RawFd};
@ -569,28 +570,19 @@ impl VirtioDevice for Net {
self.common.paused_sync = Some(Arc::new(Barrier::new(self.taps.len() + 2))); self.common.paused_sync = Some(Arc::new(Barrier::new(self.taps.len() + 2)));
let paused_sync = self.common.paused_sync.clone(); let paused_sync = self.common.paused_sync.clone();
// Retrieve seccomp filter for virtio_net_ctl thread let mut epoll_threads = Vec::new();
let virtio_net_ctl_seccomp_filter = spawn_virtio_thread(
get_seccomp_filter(&self.seccomp_action, Thread::VirtioNetCtl) &format!("{}_ctrl", &self.id),
.map_err(ActivateError::CreateSeccompFilter)?; &self.seccomp_action,
thread::Builder::new() Thread::VirtioNetCtl,
.name(format!("{}_ctrl", self.id)) &mut epoll_threads,
.spawn(move || { move || {
if !virtio_net_ctl_seccomp_filter.is_empty() {
if let Err(e) = apply_filter(&virtio_net_ctl_seccomp_filter) {
error!("Error applying seccomp filter: {:?}", e);
return;
}
}
if let Err(e) = ctrl_handler.run_ctrl(paused, paused_sync.unwrap()) { if let Err(e) = ctrl_handler.run_ctrl(paused, paused_sync.unwrap()) {
error!("Error running worker: {:?}", e); error!("Error running worker: {:?}", e);
} }
}) },
.map(|thread| self.ctrl_queue_epoll_thread = Some(thread)) )?;
.map_err(|e| { self.ctrl_queue_epoll_thread = Some(epoll_threads.remove(0));
error!("failed to clone queue EventFd: {}", e);
ActivateError::BadActivate
})?;
} }
let event_idx = self.common.feature_acked(VIRTIO_RING_F_EVENT_IDX.into()); let event_idx = self.common.feature_acked(VIRTIO_RING_F_EVENT_IDX.into());
@ -656,28 +648,18 @@ impl VirtioDevice for Net {
let paused = self.common.paused.clone(); let paused = self.common.paused.clone();
let paused_sync = self.common.paused_sync.clone(); let paused_sync = self.common.paused_sync.clone();
// Retrieve seccomp filter for virtio_net thread
let virtio_net_seccomp_filter = spawn_virtio_thread(
get_seccomp_filter(&self.seccomp_action, Thread::VirtioNet) &format!("{}_qp{}", self.id.clone(), i),
.map_err(ActivateError::CreateSeccompFilter)?; &self.seccomp_action,
thread::Builder::new() Thread::VirtioNet,
.name(format!("{}_qp{}", self.id.clone(), i)) &mut epoll_threads,
.spawn(move || { move || {
if !virtio_net_seccomp_filter.is_empty() {
if let Err(e) = apply_filter(&virtio_net_seccomp_filter) {
error!("Error applying seccomp filter: {:?}", e);
return;
}
}
if let Err(e) = handler.run(paused, paused_sync.unwrap()) { if let Err(e) = handler.run(paused, paused_sync.unwrap()) {
error!("Error running worker: {:?}", e); error!("Error running worker: {:?}", e);
} }
}) },
.map(|thread| epoll_threads.push(thread)) )?;
.map_err(|e| {
error!("failed to clone queue EventFd: {}", e);
ActivateError::BadActivate
})?;
} }
self.common.epoll_threads = Some(epoll_threads); self.common.epoll_threads = Some(epoll_threads);

View File

@ -12,10 +12,11 @@ use super::{
EpollHelperHandler, Queue, UserspaceMapping, VirtioCommon, VirtioDevice, VirtioDeviceType, EpollHelperHandler, Queue, UserspaceMapping, VirtioCommon, VirtioDevice, VirtioDeviceType,
EPOLL_HELPER_EVENT_LAST, VIRTIO_F_IOMMU_PLATFORM, VIRTIO_F_VERSION_1, EPOLL_HELPER_EVENT_LAST, VIRTIO_F_IOMMU_PLATFORM, VIRTIO_F_VERSION_1,
}; };
use crate::seccomp_filters::{get_seccomp_filter, Thread}; use crate::seccomp_filters::Thread;
use crate::thread_helper::spawn_virtio_thread;
use crate::{GuestMemoryMmap, MmapRegion}; use crate::{GuestMemoryMmap, MmapRegion};
use crate::{VirtioInterrupt, VirtioInterruptType}; use crate::{VirtioInterrupt, VirtioInterruptType};
use seccompiler::{apply_filter, SeccompAction}; use seccompiler::SeccompAction;
use std::fmt::{self, Display}; use std::fmt::{self, Display};
use std::fs::File; use std::fs::File;
use std::io; use std::io;
@ -24,7 +25,6 @@ use std::os::unix::io::AsRawFd;
use std::result; use std::result;
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
use std::sync::{Arc, Barrier}; use std::sync::{Arc, Barrier};
use std::thread;
use versionize::{VersionMap, Versionize, VersionizeResult}; use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize; use versionize_derive::Versionize;
use vm_memory::{ use vm_memory::{
@ -390,28 +390,18 @@ impl VirtioDevice for Pmem {
let paused = self.common.paused.clone(); let paused = self.common.paused.clone();
let paused_sync = self.common.paused_sync.clone(); let paused_sync = self.common.paused_sync.clone();
let mut epoll_threads = Vec::new(); let mut epoll_threads = Vec::new();
// Retrieve seccomp filter for virtio_pmem thread
let virtio_pmem_seccomp_filter = spawn_virtio_thread(
get_seccomp_filter(&self.seccomp_action, Thread::VirtioPmem) &self.id,
.map_err(ActivateError::CreateSeccompFilter)?; &self.seccomp_action,
thread::Builder::new() Thread::VirtioPmem,
.name(self.id.clone()) &mut epoll_threads,
.spawn(move || { move || {
if !virtio_pmem_seccomp_filter.is_empty() {
if let Err(e) = apply_filter(&virtio_pmem_seccomp_filter) {
error!("Error applying seccomp filter: {:?}", e);
return;
}
}
if let Err(e) = handler.run(paused, paused_sync.unwrap()) { if let Err(e) = handler.run(paused, paused_sync.unwrap()) {
error!("Error running worker: {:?}", e); error!("Error running worker: {:?}", e);
} }
}) },
.map(|thread| epoll_threads.push(thread)) )?;
.map_err(|e| {
error!("failed to clone virtio-pmem epoll thread: {}", e);
ActivateError::BadActivate
})?;
self.common.epoll_threads = Some(epoll_threads); self.common.epoll_threads = Some(epoll_threads);

View File

@ -8,17 +8,17 @@ use super::{
VirtioCommon, VirtioDevice, VirtioDeviceType, EPOLL_HELPER_EVENT_LAST, VIRTIO_F_IOMMU_PLATFORM, VirtioCommon, VirtioDevice, VirtioDeviceType, EPOLL_HELPER_EVENT_LAST, VIRTIO_F_IOMMU_PLATFORM,
VIRTIO_F_VERSION_1, VIRTIO_F_VERSION_1,
}; };
use crate::seccomp_filters::{get_seccomp_filter, Thread}; use crate::seccomp_filters::Thread;
use crate::thread_helper::spawn_virtio_thread;
use crate::GuestMemoryMmap; use crate::GuestMemoryMmap;
use crate::{VirtioInterrupt, VirtioInterruptType}; use crate::{VirtioInterrupt, VirtioInterruptType};
use seccompiler::{apply_filter, SeccompAction}; use seccompiler::SeccompAction;
use std::fs::File; use std::fs::File;
use std::io; use std::io;
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::result; use std::result;
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
use std::sync::{Arc, Barrier}; use std::sync::{Arc, Barrier};
use std::thread;
use versionize::{VersionMap, Versionize, VersionizeResult}; use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize; use versionize_derive::Versionize;
use vm_memory::{Bytes, GuestAddressSpace, GuestMemoryAtomic}; use vm_memory::{Bytes, GuestAddressSpace, GuestMemoryAtomic};
@ -236,28 +236,17 @@ impl VirtioDevice for Rng {
let paused = self.common.paused.clone(); let paused = self.common.paused.clone();
let paused_sync = self.common.paused_sync.clone(); let paused_sync = self.common.paused_sync.clone();
let mut epoll_threads = Vec::new(); let mut epoll_threads = Vec::new();
// Retrieve seccomp filter for virtio_rng thread spawn_virtio_thread(
let virtio_rng_seccomp_filter = &self.id,
get_seccomp_filter(&self.seccomp_action, Thread::VirtioRng) &self.seccomp_action,
.map_err(ActivateError::CreateSeccompFilter)?; Thread::VirtioRng,
thread::Builder::new() &mut epoll_threads,
.name(self.id.clone()) move || {
.spawn(move || {
if !virtio_rng_seccomp_filter.is_empty() {
if let Err(e) = apply_filter(&virtio_rng_seccomp_filter) {
error!("Error applying seccomp filter: {:?}", e);
return;
}
}
if let Err(e) = handler.run(paused, paused_sync.unwrap()) { if let Err(e) = handler.run(paused, paused_sync.unwrap()) {
error!("Error running worker: {:?}", e); error!("Error running worker: {:?}", e);
} }
}) },
.map(|thread| epoll_threads.push(thread)) )?;
.map_err(|e| {
error!("failed to clone the virtio-rng epoll thread: {}", e);
ActivateError::BadActivate
})?;
self.common.epoll_threads = Some(epoll_threads); self.common.epoll_threads = Some(epoll_threads);

View File

@ -20,7 +20,9 @@ pub enum Thread {
VirtioNetCtl, VirtioNetCtl,
VirtioPmem, VirtioPmem,
VirtioRng, VirtioRng,
VirtioVhostBlock,
VirtioVhostFs, VirtioVhostFs,
VirtioVhostNet,
VirtioVhostNetCtl, VirtioVhostNetCtl,
VirtioVsock, VirtioVsock,
VirtioWatchdog, VirtioWatchdog,
@ -372,6 +374,65 @@ fn virtio_vhost_net_ctl_thread_rules() -> Vec<(i64, Vec<SeccompRule>)> {
] ]
} }
fn virtio_vhost_net_thread_rules() -> Vec<(i64, Vec<SeccompRule>)> {
vec![
(libc::SYS_accept4, vec![]),
(libc::SYS_bind, vec![]),
(libc::SYS_brk, vec![]),
#[cfg(feature = "mshv")]
(libc::SYS_clock_gettime, vec![]),
(libc::SYS_close, vec![]),
(libc::SYS_dup, vec![]),
(libc::SYS_epoll_create1, 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_futex, vec![]),
(libc::SYS_getcwd, vec![]),
(libc::SYS_listen, vec![]),
(libc::SYS_munmap, vec![]),
(libc::SYS_madvise, vec![]),
(libc::SYS_read, vec![]),
(libc::SYS_recvmsg, vec![]),
(libc::SYS_rt_sigprocmask, vec![]),
(libc::SYS_rt_sigreturn, vec![]),
(libc::SYS_sendmsg, vec![]),
(libc::SYS_sendto, vec![]),
(libc::SYS_sigaltstack, vec![]),
(libc::SYS_socket, vec![]),
#[cfg(target_arch = "x86_64")]
(libc::SYS_unlink, vec![]),
#[cfg(target_arch = "aarch64")]
(libc::SYS_unlinkat, vec![]),
(libc::SYS_write, vec![]),
]
}
fn virtio_vhost_block_thread_rules() -> Vec<(i64, Vec<SeccompRule>)> {
vec![
(libc::SYS_brk, vec![]),
#[cfg(feature = "mshv")]
(libc::SYS_clock_gettime, vec![]),
(libc::SYS_close, vec![]),
(libc::SYS_dup, vec![]),
(libc::SYS_epoll_create1, 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_futex, vec![]),
(libc::SYS_munmap, vec![]),
(libc::SYS_madvise, vec![]),
(libc::SYS_read, vec![]),
(libc::SYS_rt_sigprocmask, vec![]),
(libc::SYS_sigaltstack, vec![]),
(libc::SYS_write, vec![]),
]
}
fn create_vsock_ioctl_seccomp_rule() -> Vec<SeccompRule> { fn create_vsock_ioctl_seccomp_rule() -> Vec<SeccompRule> {
or![and![Cond::new(1, ArgLen::Dword, Eq, FIONBIO,).unwrap()],] or![and![Cond::new(1, ArgLen::Dword, Eq, FIONBIO,).unwrap()],]
} }
@ -445,7 +506,9 @@ fn get_seccomp_rules(thread_type: Thread) -> Vec<(i64, Vec<SeccompRule>)> {
Thread::VirtioNetCtl => virtio_net_ctl_thread_rules(), Thread::VirtioNetCtl => virtio_net_ctl_thread_rules(),
Thread::VirtioPmem => virtio_pmem_thread_rules(), Thread::VirtioPmem => virtio_pmem_thread_rules(),
Thread::VirtioRng => virtio_rng_thread_rules(), Thread::VirtioRng => virtio_rng_thread_rules(),
Thread::VirtioVhostBlock => virtio_vhost_block_thread_rules(),
Thread::VirtioVhostFs => virtio_vhost_fs_thread_rules(), Thread::VirtioVhostFs => virtio_vhost_fs_thread_rules(),
Thread::VirtioVhostNet => virtio_vhost_net_thread_rules(),
Thread::VirtioVhostNetCtl => virtio_vhost_net_ctl_thread_rules(), Thread::VirtioVhostNetCtl => virtio_vhost_net_ctl_thread_rules(),
Thread::VirtioVsock => virtio_vsock_thread_rules(), Thread::VirtioVsock => virtio_vsock_thread_rules(),
Thread::VirtioWatchdog => virtio_watchdog_thread_rules(), Thread::VirtioWatchdog => virtio_watchdog_thread_rules(),

View File

@ -0,0 +1,43 @@
// Copyright © 2021 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
use crate::{
seccomp_filters::{get_seccomp_filter, Thread},
ActivateError,
};
use seccompiler::{apply_filter, SeccompAction};
use std::thread::{self, JoinHandle};
pub(crate) fn spawn_virtio_thread<F>(
name: &str,
seccomp_action: &SeccompAction,
thread_type: Thread,
epoll_threads: &mut Vec<JoinHandle<()>>,
f: F,
) -> Result<(), ActivateError>
where
F: FnOnce(),
F: Send + 'static,
{
let seccomp_filter = get_seccomp_filter(seccomp_action, thread_type)
.map_err(ActivateError::CreateSeccompFilter)?;
thread::Builder::new()
.name(name.to_string())
.spawn(move || {
if !seccomp_filter.is_empty() {
if let Err(e) = apply_filter(&seccomp_filter) {
error!("Error applying seccomp filter: {:?}", e);
return;
}
}
f()
})
.map(|thread| epoll_threads.push(thread))
.map_err(|e| {
error!("Failed to spawn thread for {}: {}", name, e);
ActivateError::BadActivate
})
}

View File

@ -1,15 +1,16 @@
// Copyright 2019 Intel Corporation. All Rights Reserved. // Copyright 2019 Intel Corporation. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use super::super::{ use super::super::{ActivateResult, Queue, VirtioCommon, VirtioDevice, VirtioDeviceType};
ActivateError, ActivateResult, Queue, VirtioCommon, VirtioDevice, VirtioDeviceType,
};
use super::vu_common_ctrl::{VhostUserConfig, VhostUserHandle}; use super::vu_common_ctrl::{VhostUserConfig, VhostUserHandle};
use super::{Error, Result, DEFAULT_VIRTIO_FEATURES}; use super::{Error, Result, DEFAULT_VIRTIO_FEATURES};
use crate::seccomp_filters::Thread;
use crate::thread_helper::spawn_virtio_thread;
use crate::vhost_user::VhostUserCommon; use crate::vhost_user::VhostUserCommon;
use crate::VirtioInterrupt; use crate::VirtioInterrupt;
use crate::{GuestMemoryMmap, GuestRegionMmap}; use crate::{GuestMemoryMmap, GuestRegionMmap};
use block_util::VirtioBlockConfig; use block_util::VirtioBlockConfig;
use seccompiler::SeccompAction;
use std::mem; use std::mem;
use std::result; use std::result;
use std::sync::{Arc, Barrier, Mutex}; use std::sync::{Arc, Barrier, Mutex};
@ -57,11 +58,17 @@ pub struct Blk {
config: VirtioBlockConfig, config: VirtioBlockConfig,
guest_memory: Option<GuestMemoryAtomic<GuestMemoryMmap>>, guest_memory: Option<GuestMemoryAtomic<GuestMemoryMmap>>,
epoll_thread: Option<thread::JoinHandle<()>>, epoll_thread: Option<thread::JoinHandle<()>>,
seccomp_action: SeccompAction,
} }
impl Blk { impl Blk {
/// Create a new vhost-user-blk device /// Create a new vhost-user-blk device
pub fn new(id: String, vu_cfg: VhostUserConfig, restoring: bool) -> Result<Blk> { pub fn new(
id: String,
vu_cfg: VhostUserConfig,
restoring: bool,
seccomp_action: SeccompAction,
) -> Result<Blk> {
let num_queues = vu_cfg.num_queues; let num_queues = vu_cfg.num_queues;
if restoring { if restoring {
@ -85,6 +92,7 @@ impl Blk {
config: VirtioBlockConfig::default(), config: VirtioBlockConfig::default(),
guest_memory: None, guest_memory: None,
epoll_thread: None, epoll_thread: None,
seccomp_action,
}); });
} }
@ -171,6 +179,7 @@ impl Blk {
config, config,
guest_memory: None, guest_memory: None,
epoll_thread: None, epoll_thread: None,
seccomp_action,
}) })
} }
@ -298,18 +307,20 @@ impl VirtioDevice for Blk {
let paused = self.common.paused.clone(); let paused = self.common.paused.clone();
let paused_sync = self.common.paused_sync.clone(); let paused_sync = self.common.paused_sync.clone();
thread::Builder::new() let mut epoll_threads = Vec::new();
.name(self.id.to_string())
.spawn(move || { spawn_virtio_thread(
&self.id,
&self.seccomp_action,
Thread::VirtioVhostBlock,
&mut epoll_threads,
move || {
if let Err(e) = handler.run(paused, paused_sync.unwrap()) { if let Err(e) = handler.run(paused, paused_sync.unwrap()) {
error!("Error running vhost-user-blk worker: {:?}", e); error!("Error running worker: {:?}", e);
} }
}) },
.map(|thread| self.epoll_thread = Some(thread)) )?;
.map_err(|e| { self.epoll_thread = Some(epoll_threads.remove(0));
error!("failed to clone queue EventFd: {}", e);
ActivateError::BadActivate
})?;
Ok(()) Ok(())
} }

View File

@ -3,7 +3,8 @@
use super::vu_common_ctrl::VhostUserHandle; use super::vu_common_ctrl::VhostUserHandle;
use super::{Error, Result, DEFAULT_VIRTIO_FEATURES}; use super::{Error, Result, DEFAULT_VIRTIO_FEATURES};
use crate::seccomp_filters::{get_seccomp_filter, Thread}; use crate::seccomp_filters::Thread;
use crate::thread_helper::spawn_virtio_thread;
use crate::vhost_user::VhostUserCommon; use crate::vhost_user::VhostUserCommon;
use crate::{ use crate::{
ActivateError, ActivateResult, Queue, UserspaceMapping, VirtioCommon, VirtioDevice, ActivateError, ActivateResult, Queue, UserspaceMapping, VirtioCommon, VirtioDevice,
@ -11,7 +12,7 @@ use crate::{
}; };
use crate::{GuestMemoryMmap, GuestRegionMmap, MmapRegion}; use crate::{GuestMemoryMmap, GuestRegionMmap, MmapRegion};
use libc::{self, c_void, off64_t, pread64, pwrite64}; use libc::{self, c_void, off64_t, pread64, pwrite64};
use seccompiler::{apply_filter, SeccompAction}; use seccompiler::SeccompAction;
use std::io; use std::io;
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::result; use std::result;
@ -549,28 +550,19 @@ impl VirtioDevice for Fs {
let paused = self.common.paused.clone(); let paused = self.common.paused.clone();
let paused_sync = self.common.paused_sync.clone(); let paused_sync = self.common.paused_sync.clone();
let virtio_vhost_fs_seccomp_filter = let mut epoll_threads = Vec::new();
get_seccomp_filter(&self.seccomp_action, Thread::VirtioVhostFs) spawn_virtio_thread(
.map_err(ActivateError::CreateSeccompFilter)?; &self.id,
&self.seccomp_action,
thread::Builder::new() Thread::VirtioVhostFs,
.name(self.id.to_string()) &mut epoll_threads,
.spawn(move || { move || {
if !virtio_vhost_fs_seccomp_filter.is_empty() {
if let Err(e) = apply_filter(&virtio_vhost_fs_seccomp_filter) {
error!("Error applying seccomp filter: {:?}", e);
return;
}
}
if let Err(e) = handler.run(paused, paused_sync.unwrap()) { if let Err(e) = handler.run(paused, paused_sync.unwrap()) {
error!("Error running vhost-user-fs worker: {:?}", e); error!("Error running worker: {:?}", e);
} }
}) },
.map(|thread| self.epoll_thread = Some(thread)) )?;
.map_err(|e| { self.epoll_thread = Some(epoll_threads.remove(0));
error!("failed to clone queue EventFd: {}", e);
ActivateError::BadActivate
})?;
event!("virtio-device", "activated", "id", &self.id); event!("virtio-device", "activated", "id", &self.id);
Ok(()) Ok(())

View File

@ -1,17 +1,18 @@
// Copyright 2019 Intel Corporation. All Rights Reserved. // Copyright 2019 Intel Corporation. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::seccomp_filters::{get_seccomp_filter, Thread}; use crate::seccomp_filters::Thread;
use crate::thread_helper::spawn_virtio_thread;
use crate::vhost_user::vu_common_ctrl::{VhostUserConfig, VhostUserHandle}; use crate::vhost_user::vu_common_ctrl::{VhostUserConfig, VhostUserHandle};
use crate::vhost_user::{Error, Result, VhostUserCommon}; use crate::vhost_user::{Error, Result, VhostUserCommon};
use crate::{ use crate::{
ActivateError, ActivateResult, EpollHelper, EpollHelperError, EpollHelperHandler, Queue, ActivateResult, EpollHelper, EpollHelperError, EpollHelperHandler, Queue, VirtioCommon,
VirtioCommon, VirtioDevice, VirtioDeviceType, VirtioInterrupt, EPOLL_HELPER_EVENT_LAST, VirtioDevice, VirtioDeviceType, VirtioInterrupt, EPOLL_HELPER_EVENT_LAST,
VIRTIO_F_RING_EVENT_IDX, VIRTIO_F_VERSION_1, VIRTIO_F_RING_EVENT_IDX, VIRTIO_F_VERSION_1,
}; };
use crate::{GuestMemoryMmap, GuestRegionMmap}; use crate::{GuestMemoryMmap, GuestRegionMmap};
use net_util::{build_net_config_space, CtrlQueue, MacAddr, VirtioNetConfig}; use net_util::{build_net_config_space, CtrlQueue, MacAddr, VirtioNetConfig};
use seccompiler::{apply_filter, SeccompAction}; use seccompiler::SeccompAction;
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::result; use std::result;
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
@ -332,28 +333,19 @@ impl VirtioDevice for Net {
self.common.paused_sync = Some(Arc::new(Barrier::new(3))); self.common.paused_sync = Some(Arc::new(Barrier::new(3)));
let paused_sync = self.common.paused_sync.clone(); let paused_sync = self.common.paused_sync.clone();
// Retrieve seccomp filter for virtio_net_ctl thread let mut epoll_threads = Vec::new();
let virtio_vhost_net_ctl_seccomp_filter = spawn_virtio_thread(
get_seccomp_filter(&self.seccomp_action, Thread::VirtioVhostNetCtl) &format!("{}_ctrl", &self.id),
.map_err(ActivateError::CreateSeccompFilter)?; &self.seccomp_action,
thread::Builder::new() Thread::VirtioVhostNetCtl,
.name(format!("{}_ctrl", self.id)) &mut epoll_threads,
.spawn(move || { move || {
if !virtio_vhost_net_ctl_seccomp_filter.is_empty() {
if let Err(e) = apply_filter(&virtio_vhost_net_ctl_seccomp_filter) {
error!("Error applying seccomp filter: {:?}", e);
return;
}
}
if let Err(e) = ctrl_handler.run_ctrl(paused, paused_sync.unwrap()) { if let Err(e) = ctrl_handler.run_ctrl(paused, paused_sync.unwrap()) {
error!("Error running worker: {:?}", e); error!("Error running worker: {:?}", e);
} }
}) },
.map(|thread| self.ctrl_queue_epoll_thread = Some(thread)) )?;
.map_err(|e| { self.ctrl_queue_epoll_thread = Some(epoll_threads.remove(0));
error!("failed to clone queue EventFd: {}", e);
ActivateError::BadActivate
})?;
} }
let slave_req_handler: Option<MasterReqHandler<SlaveReqHandler>> = None; let slave_req_handler: Option<MasterReqHandler<SlaveReqHandler>> = None;
@ -383,18 +375,19 @@ impl VirtioDevice for Net {
let paused = self.common.paused.clone(); let paused = self.common.paused.clone();
let paused_sync = self.common.paused_sync.clone(); let paused_sync = self.common.paused_sync.clone();
thread::Builder::new() let mut epoll_threads = Vec::new();
.name(self.id.to_string()) spawn_virtio_thread(
.spawn(move || { &self.id,
&self.seccomp_action,
Thread::VirtioVhostNet,
&mut epoll_threads,
move || {
if let Err(e) = handler.run(paused, paused_sync.unwrap()) { if let Err(e) = handler.run(paused, paused_sync.unwrap()) {
error!("Error running vhost-user-net worker: {:?}", e); error!("Error running worker: {:?}", e);
} }
}) },
.map(|thread| self.epoll_thread = Some(thread)) )?;
.map_err(|e| { self.epoll_thread = Some(epoll_threads.remove(0));
error!("failed to clone queue EventFd: {}", e);
ActivateError::BadActivate
})?;
Ok(()) Ok(())
} }

View File

@ -28,24 +28,23 @@
/// - a backend FD. /// - a backend FD.
/// ///
use super::{VsockBackend, VsockPacket}; use super::{VsockBackend, VsockPacket};
use crate::seccomp_filters::{get_seccomp_filter, Thread}; use crate::seccomp_filters::Thread;
use crate::Error as DeviceError; use crate::Error as DeviceError;
use crate::GuestMemoryMmap; use crate::GuestMemoryMmap;
use crate::VirtioInterrupt; use crate::VirtioInterrupt;
use crate::{ use crate::{
ActivateError, ActivateResult, EpollHelper, EpollHelperError, EpollHelperHandler, Queue, thread_helper::spawn_virtio_thread, ActivateResult, EpollHelper, EpollHelperError,
VirtioCommon, VirtioDevice, VirtioDeviceType, VirtioInterruptType, EPOLL_HELPER_EVENT_LAST, EpollHelperHandler, Queue, VirtioCommon, VirtioDevice, VirtioDeviceType, VirtioInterruptType,
VIRTIO_F_IN_ORDER, VIRTIO_F_IOMMU_PLATFORM, VIRTIO_F_VERSION_1, EPOLL_HELPER_EVENT_LAST, VIRTIO_F_IN_ORDER, VIRTIO_F_IOMMU_PLATFORM, VIRTIO_F_VERSION_1,
}; };
use byteorder::{ByteOrder, LittleEndian}; use byteorder::{ByteOrder, LittleEndian};
use seccompiler::{apply_filter, SeccompAction}; use seccompiler::SeccompAction;
use std::io; use std::io;
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::path::PathBuf; use std::path::PathBuf;
use std::result; use std::result;
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
use std::sync::{Arc, Barrier, RwLock}; use std::sync::{Arc, Barrier, RwLock};
use std::thread;
use versionize::{VersionMap, Versionize, VersionizeResult}; use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize; use versionize_derive::Versionize;
use vm_memory::{GuestAddressSpace, GuestMemoryAtomic}; use vm_memory::{GuestAddressSpace, GuestMemoryAtomic};
@ -434,28 +433,18 @@ where
let paused = self.common.paused.clone(); let paused = self.common.paused.clone();
let paused_sync = self.common.paused_sync.clone(); let paused_sync = self.common.paused_sync.clone();
let mut epoll_threads = Vec::new(); let mut epoll_threads = Vec::new();
// Retrieve seccomp filter for virtio_vsock thread
let virtio_vsock_seccomp_filter = spawn_virtio_thread(
get_seccomp_filter(&self.seccomp_action, Thread::VirtioVsock) &self.id,
.map_err(ActivateError::CreateSeccompFilter)?; &self.seccomp_action,
thread::Builder::new() Thread::VirtioVsock,
.name(self.id.clone()) &mut epoll_threads,
.spawn(move || { move || {
if !virtio_vsock_seccomp_filter.is_empty() {
if let Err(e) = apply_filter(&virtio_vsock_seccomp_filter) {
error!("Error applying seccomp filter: {:?}", e);
return;
}
}
if let Err(e) = handler.run(paused, paused_sync.unwrap()) { if let Err(e) = handler.run(paused, paused_sync.unwrap()) {
error!("Error running worker: {:?}", e); error!("Error running worker: {:?}", e);
} }
}) },
.map(|thread| epoll_threads.push(thread)) )?;
.map_err(|e| {
error!("failed to clone the vsock epoll thread: {}", e);
ActivateError::BadActivate
})?;
self.common.epoll_threads = Some(epoll_threads); self.common.epoll_threads = Some(epoll_threads);
@ -513,6 +502,7 @@ mod tests {
use super::super::*; use super::super::*;
use super::*; use super::*;
use crate::vsock::device::{BACKEND_EVENT, EVT_QUEUE_EVENT, RX_QUEUE_EVENT, TX_QUEUE_EVENT}; use crate::vsock::device::{BACKEND_EVENT, EVT_QUEUE_EVENT, RX_QUEUE_EVENT, TX_QUEUE_EVENT};
use crate::ActivateError;
use libc::EFD_NONBLOCK; use libc::EFD_NONBLOCK;
#[test] #[test]

View File

@ -10,18 +10,18 @@ use super::{
ActivateError, ActivateResult, EpollHelper, EpollHelperError, EpollHelperHandler, Queue, ActivateError, ActivateResult, EpollHelper, EpollHelperError, EpollHelperHandler, Queue,
VirtioCommon, VirtioDevice, VirtioDeviceType, EPOLL_HELPER_EVENT_LAST, VIRTIO_F_VERSION_1, VirtioCommon, VirtioDevice, VirtioDeviceType, EPOLL_HELPER_EVENT_LAST, VIRTIO_F_VERSION_1,
}; };
use crate::seccomp_filters::{get_seccomp_filter, Thread}; use crate::seccomp_filters::Thread;
use crate::thread_helper::spawn_virtio_thread;
use crate::GuestMemoryMmap; use crate::GuestMemoryMmap;
use crate::{VirtioInterrupt, VirtioInterruptType}; use crate::{VirtioInterrupt, VirtioInterruptType};
use anyhow::anyhow; use anyhow::anyhow;
use seccompiler::{apply_filter, SeccompAction}; use seccompiler::SeccompAction;
use std::fs::File; use std::fs::File;
use std::io::{self, Read}; use std::io::{self, Read};
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::result; use std::result;
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
use std::sync::{Arc, Barrier, Mutex}; use std::sync::{Arc, Barrier, Mutex};
use std::thread;
use std::time::Instant; use std::time::Instant;
use versionize::{VersionMap, Versionize, VersionizeResult}; use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize; use versionize_derive::Versionize;
@ -318,29 +318,18 @@ impl VirtioDevice for Watchdog {
let paused = self.common.paused.clone(); let paused = self.common.paused.clone();
let paused_sync = self.common.paused_sync.clone(); let paused_sync = self.common.paused_sync.clone();
let mut epoll_threads = Vec::new(); let mut epoll_threads = Vec::new();
// Retrieve seccomp filter for virtio_watchdog thread
let virtio_watchdog_seccomp_filter =
get_seccomp_filter(&self.seccomp_action, Thread::VirtioWatchdog)
.map_err(ActivateError::CreateSeccompFilter)?;
thread::Builder::new()
.name(self.id.clone())
.spawn(move || {
if !virtio_watchdog_seccomp_filter.is_empty() {
if let Err(e) = apply_filter(&virtio_watchdog_seccomp_filter) {
error!("Error applying seccomp filter: {:?}", e);
return;
}
}
spawn_virtio_thread(
&self.id,
&self.seccomp_action,
Thread::VirtioWatchdog,
&mut epoll_threads,
move || {
if let Err(e) = handler.run(paused, paused_sync.unwrap()) { if let Err(e) = handler.run(paused, paused_sync.unwrap()) {
error!("Error running worker: {:?}", e); error!("Error running worker: {:?}", e);
} }
}) },
.map(|thread| epoll_threads.push(thread)) )?;
.map_err(|e| {
error!("failed to clone the virtio-watchdog epoll thread: {}", e);
ActivateError::BadActivate
})?;
self.common.epoll_threads = Some(epoll_threads); self.common.epoll_threads = Some(epoll_threads);

View File

@ -1862,7 +1862,12 @@ impl DeviceManager {
queue_size: disk_cfg.queue_size, queue_size: disk_cfg.queue_size,
}; };
let vhost_user_block_device = Arc::new(Mutex::new( let vhost_user_block_device = Arc::new(Mutex::new(
match virtio_devices::vhost_user::Blk::new(id.clone(), vu_cfg, self.restoring) { match virtio_devices::vhost_user::Blk::new(
id.clone(),
vu_cfg,
self.restoring,
self.seccomp_action.clone(),
) {
Ok(vub_device) => vub_device, Ok(vub_device) => vub_device,
Err(e) => { Err(e) => {
return Err(DeviceManagerError::CreateVhostUserBlk(e)); return Err(DeviceManagerError::CreateVhostUserBlk(e));