virtio-devices: seccomp: Add seccomp filters for virtio_vsock thread

This patch enables the seccomp filters for the virtio_vsock worker
thread.

Partially fixes: #925

Signed-off-by: Bo Chen <chen.bo@intel.com>
This commit is contained in:
Bo Chen 2020-09-08 19:35:03 -07:00 committed by Rob Bradford
parent 1175fa2bc7
commit 3c923f0727
4 changed files with 70 additions and 2 deletions

View File

@ -5,7 +5,9 @@
// SPDX-License-Identifier: Apache-2.0
use seccomp::{
allow_syscall, BpfProgram, Error, SeccompAction, SeccompError, SeccompFilter, SyscallRuleSet,
allow_syscall, allow_syscall_if, BpfProgram, Error, SeccompAction, SeccompCmpArgLen as ArgLen,
SeccompCmpOp::Eq, SeccompCondition as Cond, SeccompError, SeccompFilter, SeccompRule,
SyscallRuleSet,
};
use std::convert::TryInto;
@ -24,11 +26,35 @@ pub enum Thread {
VirtioVhostFs,
VirtioVhostNet,
VirtioVhostNetCtl,
VirtioVsock,
}
/// Shorthand for chaining `SeccompCondition`s with the `and` operator in a `SeccompRule`.
/// The rule will take the `Allow` action if _all_ the conditions are true.
///
/// [`Allow`]: enum.SeccompAction.html
/// [`SeccompCondition`]: struct.SeccompCondition.html
/// [`SeccompRule`]: struct.SeccompRule.html
macro_rules! and {
($($x:expr,)*) => (SeccompRule::new(vec![$($x),*], SeccompAction::Allow));
($($x:expr),*) => (SeccompRule::new(vec![$($x),*], SeccompAction::Allow))
}
/// Shorthand for chaining `SeccompRule`s with the `or` operator in a `SeccompFilter`.
///
/// [`SeccompFilter`]: struct.SeccompFilter.html
/// [`SeccompRule`]: struct.SeccompRule.html
macro_rules! or {
($($x:expr,)*) => (vec![$($x),*]);
($($x:expr),*) => (vec![$($x),*])
}
// Define io_uring syscalls as they are not yet part of libc.
const SYS_IO_URING_ENTER: i64 = 426;
// See include/uapi/asm-generic/ioctls.h in the kernel code.
const FIONBIO: u64 = 0x5421;
fn virtio_balloon_thread_rules() -> Result<Vec<SyscallRuleSet>, Error> {
Ok(vec![
allow_syscall(libc::SYS_brk),
@ -349,6 +375,33 @@ fn virtio_vhost_net_ctl_thread_rules() -> Result<Vec<SyscallRuleSet>, Error> {
])
}
fn create_vsock_ioctl_seccomp_rule() -> Result<Vec<SeccompRule>, Error> {
Ok(or![and![Cond::new(1, ArgLen::DWORD, Eq, FIONBIO,)?],])
}
fn virtio_vsock_thread_rules() -> Result<Vec<SyscallRuleSet>, Error> {
Ok(vec![
allow_syscall(libc::SYS_accept4),
allow_syscall(libc::SYS_close),
allow_syscall(libc::SYS_dup),
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_if(libc::SYS_ioctl, create_vsock_ioctl_seccomp_rule()?),
allow_syscall(libc::SYS_futex),
allow_syscall(libc::SYS_madvise),
allow_syscall(libc::SYS_munmap),
allow_syscall(libc::SYS_read),
allow_syscall(libc::SYS_recvfrom),
allow_syscall(libc::SYS_rt_sigprocmask),
allow_syscall(libc::SYS_sigaltstack),
allow_syscall(libc::SYS_write),
])
}
fn get_seccomp_filter_trap(thread_type: Thread) -> Result<SeccompFilter, Error> {
let rules = match thread_type {
Thread::VirtioBalloon => virtio_balloon_thread_rules()?,
@ -365,6 +418,7 @@ fn get_seccomp_filter_trap(thread_type: Thread) -> Result<SeccompFilter, Error>
Thread::VirtioVhostFs => virtio_vhost_fs_thread_rules()?,
Thread::VirtioVhostNet => virtio_vhost_net_thread_rules()?,
Thread::VirtioVhostNetCtl => virtio_vhost_net_ctl_thread_rules()?,
Thread::VirtioVsock => virtio_vsock_thread_rules()?,
};
Ok(SeccompFilter::new(
@ -389,6 +443,7 @@ fn get_seccomp_filter_log(thread_type: Thread) -> Result<SeccompFilter, Error> {
Thread::VirtioVhostFs => virtio_vhost_fs_thread_rules()?,
Thread::VirtioVhostNet => virtio_vhost_net_thread_rules()?,
Thread::VirtioVhostNetCtl => virtio_vhost_net_ctl_thread_rules()?,
Thread::VirtioVsock => virtio_vsock_thread_rules()?,
};
Ok(SeccompFilter::new(

View File

@ -9,6 +9,7 @@
// found in the THIRD-PARTY file.
use super::{VsockBackend, VsockPacket};
use crate::seccomp_filters::{get_seccomp_filter, Thread};
use crate::Error as DeviceError;
use crate::VirtioInterrupt;
use crate::{
@ -37,6 +38,7 @@ use anyhow::anyhow;
/// - a backend FD.
///
use byteorder::{ByteOrder, LittleEndian};
use seccomp::{SeccompAction, SeccompFilter};
use std::io;
use std::os::unix::io::AsRawFd;
use std::path::PathBuf;
@ -300,6 +302,7 @@ pub struct Vsock<B: VsockBackend> {
cid: u64,
backend: Arc<RwLock<B>>,
path: PathBuf,
seccomp_action: SeccompAction,
}
#[derive(Serialize, Deserialize)]
@ -320,6 +323,7 @@ where
path: PathBuf,
backend: B,
iommu: bool,
seccomp_action: SeccompAction,
) -> io::Result<Vsock<B>> {
let mut avail_features = 1u64 << VIRTIO_F_VERSION_1 | 1u64 << VIRTIO_F_IN_ORDER;
@ -339,6 +343,7 @@ where
cid,
backend: Arc::new(RwLock::new(backend)),
path,
seccomp_action,
})
}
@ -446,10 +451,16 @@ where
let paused = self.common.paused.clone();
let paused_sync = self.common.paused_sync.clone();
let mut epoll_threads = Vec::new();
// Retrieve seccomp filter for virtio_vsock thread
let virtio_vsock_seccomp_filter =
get_seccomp_filter(&self.seccomp_action, Thread::VirtioVsock)
.map_err(ActivateError::CreateSeccompFilter)?;
thread::Builder::new()
.name("virtio_vsock".to_string())
.spawn(move || {
if let Err(e) = handler.run(paused, paused_sync.unwrap()) {
if let Err(e) = SeccompFilter::apply(virtio_vsock_seccomp_filter) {
error!("Error applying seccomp filter: {:?}", e);
} else if let Err(e) = handler.run(paused, paused_sync.unwrap()) {
error!("Error running worker: {:?}", e);
}
})

View File

@ -273,6 +273,7 @@ mod tests {
PathBuf::from("/test/sock"),
TestBackend::new(),
false,
seccomp::SeccompAction::Trap,
)
.unwrap(),
}

View File

@ -2378,6 +2378,7 @@ impl DeviceManager {
vsock_cfg.socket.clone(),
backend,
vsock_cfg.iommu,
self.seccomp_action.clone(),
)
.map_err(DeviceManagerError::CreateVirtioVsock)?,
));