mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-03-20 07:58:55 +00:00
virtio-devices: seccomp: Add seccomp_filter module
This patch added the seccomp_filter module to the virtio-devices crate by taking reference code from the vmm crate. This patch also adds allowed-list for the virtio-block worker thread. Partially fixes: #925 Signed-off-by: Bo Chen <chen.bo@intel.com>
This commit is contained in:
parent
ff7ed8f628
commit
704edd544c
@ -13,7 +13,7 @@ io_uring = ["block_util/io_uring"]
|
||||
[dependencies]
|
||||
anyhow = "1.0"
|
||||
arc-swap = ">=0.4.4"
|
||||
block_util = { path = "../block_util" }
|
||||
block_util = { path = "../block_util" }
|
||||
byteorder = "1.3.4"
|
||||
devices = { path = "../devices" }
|
||||
epoll = ">=4.0.1"
|
||||
@ -23,6 +23,7 @@ log = "0.4.11"
|
||||
net_gen = { path = "../net_gen" }
|
||||
net_util = { path = "../net_util" }
|
||||
pci = { path = "../pci", optional = true }
|
||||
seccomp = { git = "https://github.com/firecracker-microvm/firecracker", tag = "v0.21.1" }
|
||||
serde = ">=1.0.27"
|
||||
serde_derive = ">=1.0.27"
|
||||
serde_json = ">=1.0.9"
|
||||
@ -36,4 +37,3 @@ vm-memory = { version = "0.2.1", features = ["backend-mmap", "backend-atomic"] }
|
||||
vm-migration = { path = "../vm-migration" }
|
||||
vm-virtio = { path = "../vm-virtio" }
|
||||
vmm-sys-util = ">=0.3.1"
|
||||
|
||||
|
@ -13,10 +13,12 @@ use super::{
|
||||
ActivateError, ActivateResult, EpollHelper, EpollHelperError, EpollHelperHandler, Queue,
|
||||
VirtioDevice, VirtioDeviceType, VirtioInterruptType, EPOLL_HELPER_EVENT_LAST,
|
||||
};
|
||||
use crate::seccomp_filters::{get_seccomp_filter, Thread};
|
||||
use crate::VirtioInterrupt;
|
||||
use anyhow::anyhow;
|
||||
use block_util::{build_disk_image_id, Request, RequestType, VirtioBlockConfig};
|
||||
use libc::EFD_NONBLOCK;
|
||||
use seccomp::{SeccompAction, SeccompFilter};
|
||||
use std::collections::HashMap;
|
||||
use std::io::{self, Read, Seek, SeekFrom, Write};
|
||||
use std::num::Wrapping;
|
||||
@ -268,6 +270,7 @@ pub struct Block<T: DiskFile> {
|
||||
queue_size: Vec<u16>,
|
||||
writeback: Arc<AtomicBool>,
|
||||
counters: BlockCounters,
|
||||
seccomp_action: SeccompAction,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@ -283,6 +286,7 @@ impl<T: DiskFile> Block<T> {
|
||||
/// Create a new virtio block device that operates on the given file.
|
||||
///
|
||||
/// The given file must be seekable and sizable.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
id: String,
|
||||
mut disk_image: T,
|
||||
@ -291,6 +295,7 @@ impl<T: DiskFile> Block<T> {
|
||||
iommu: bool,
|
||||
num_queues: usize,
|
||||
queue_size: u16,
|
||||
seccomp_action: SeccompAction,
|
||||
) -> io::Result<Block<T>> {
|
||||
let disk_size = disk_image.seek(SeekFrom::End(0))? as u64;
|
||||
if disk_size % SECTOR_SIZE != 0 {
|
||||
@ -343,6 +348,7 @@ impl<T: DiskFile> Block<T> {
|
||||
queue_size: vec![queue_size; num_queues],
|
||||
writeback: Arc::new(AtomicBool::new(true)),
|
||||
counters: BlockCounters::default(),
|
||||
seccomp_action,
|
||||
})
|
||||
}
|
||||
|
||||
@ -527,9 +533,19 @@ impl<T: 'static + DiskFile + Send> VirtioDevice for Block<T> {
|
||||
handler.queue.set_event_idx(event_idx);
|
||||
|
||||
let paused = self.paused.clone();
|
||||
|
||||
// Retrieve seccomp filter for virtio_blk thread
|
||||
let api_seccomp_filter = get_seccomp_filter(&self.seccomp_action, Thread::VirtioBlk)
|
||||
.map_err(ActivateError::CreateSeccompFilter)?;
|
||||
|
||||
thread::Builder::new()
|
||||
.name("virtio_blk".to_string())
|
||||
.spawn(move || handler.run(paused))
|
||||
.spawn(move || {
|
||||
SeccompFilter::apply(api_seccomp_filter)
|
||||
.map_err(EpollHelperError::ApplySeccompFilter)?;
|
||||
|
||||
handler.run(paused)
|
||||
})
|
||||
.map(|thread| epoll_threads.push(thread))
|
||||
.map_err(|e| {
|
||||
error!("failed to clone the virtio-blk epoll thread: {}", e);
|
||||
|
@ -25,6 +25,7 @@ pub enum EpollHelperError {
|
||||
CreateFd(std::io::Error),
|
||||
Ctl(std::io::Error),
|
||||
Wait(std::io::Error),
|
||||
ApplySeccompFilter(seccomp::Error),
|
||||
}
|
||||
|
||||
pub const EPOLL_HELPER_EVENT_PAUSE: u16 = 0;
|
||||
|
@ -41,6 +41,7 @@ pub mod net;
|
||||
pub mod net_util;
|
||||
mod pmem;
|
||||
mod rng;
|
||||
pub mod seccomp_filters;
|
||||
pub mod transport;
|
||||
pub mod vhost_user;
|
||||
pub mod vsock;
|
||||
@ -97,6 +98,8 @@ pub enum ActivateError {
|
||||
VhostUserBlkSetup(vhost_user::Error),
|
||||
/// Failed to reset vhost-user daemon.
|
||||
VhostUserReset(vhost_user::Error),
|
||||
/// Cannot create seccomp filter
|
||||
CreateSeccompFilter(seccomp::SeccompError),
|
||||
}
|
||||
|
||||
pub type ActivateResult = std::result::Result<(), ActivateError>;
|
||||
|
91
virtio-devices/src/seccomp_filters.rs
Normal file
91
virtio-devices/src/seccomp_filters.rs
Normal file
@ -0,0 +1,91 @@
|
||||
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
//
|
||||
// Copyright © 2020 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use seccomp::{
|
||||
allow_syscall, BpfProgram, Error, SeccompAction, SeccompError, SeccompFilter, SyscallRuleSet,
|
||||
};
|
||||
use std::convert::TryInto;
|
||||
|
||||
pub enum Thread {
|
||||
VirtioBlk,
|
||||
}
|
||||
|
||||
// The filter containing the allowed syscall rules required by the
|
||||
// virtio_blk thread to function.
|
||||
fn virtio_blk_thread_rules() -> Result<Vec<SyscallRuleSet>, Error> {
|
||||
Ok(vec![
|
||||
allow_syscall(libc::SYS_brk),
|
||||
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(libc::SYS_fallocate),
|
||||
allow_syscall(libc::SYS_fdatasync),
|
||||
allow_syscall(libc::SYS_fsync),
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
allow_syscall(libc::SYS_ftruncate),
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
// The definition of libc::SYS_ftruncate is missing on AArch64.
|
||||
// Use a hard-code number instead.
|
||||
allow_syscall(46),
|
||||
allow_syscall(libc::SYS_futex),
|
||||
allow_syscall(libc::SYS_lseek),
|
||||
allow_syscall(libc::SYS_madvise),
|
||||
allow_syscall(libc::SYS_mmap),
|
||||
allow_syscall(libc::SYS_mprotect),
|
||||
allow_syscall(libc::SYS_munmap),
|
||||
allow_syscall(libc::SYS_openat),
|
||||
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<SeccompFilter, Error> {
|
||||
let rules = match thread_type {
|
||||
Thread::VirtioBlk => virtio_blk_thread_rules()?,
|
||||
};
|
||||
|
||||
Ok(SeccompFilter::new(
|
||||
rules.into_iter().collect(),
|
||||
SeccompAction::Trap,
|
||||
)?)
|
||||
}
|
||||
|
||||
fn get_seccomp_filter_log(thread_type: Thread) -> Result<SeccompFilter, Error> {
|
||||
let rules = match thread_type {
|
||||
Thread::VirtioBlk => virtio_blk_thread_rules()?,
|
||||
};
|
||||
|
||||
Ok(SeccompFilter::new(
|
||||
rules.into_iter().collect(),
|
||||
SeccompAction::Log,
|
||||
)?)
|
||||
}
|
||||
|
||||
/// Generate a BPF program based on the seccomp_action value
|
||||
pub fn get_seccomp_filter(
|
||||
seccomp_action: &SeccompAction,
|
||||
thread_type: Thread,
|
||||
) -> Result<BpfProgram, SeccompError> {
|
||||
match seccomp_action {
|
||||
SeccompAction::Allow => Ok(vec![]),
|
||||
SeccompAction::Log => get_seccomp_filter_log(thread_type)
|
||||
.and_then(|filter| filter.try_into())
|
||||
.map_err(SeccompError::SeccompFilter),
|
||||
_ => get_seccomp_filter_trap(thread_type)
|
||||
.and_then(|filter| filter.try_into())
|
||||
.map_err(SeccompError::SeccompFilter),
|
||||
}
|
||||
}
|
@ -54,6 +54,7 @@ use pci::{
|
||||
VfioPciDevice,
|
||||
};
|
||||
use qcow::{self, ImageType, QcowFile};
|
||||
use seccomp::SeccompAction;
|
||||
#[cfg(feature = "pci_support")]
|
||||
use std::any::Any;
|
||||
use std::collections::HashMap;
|
||||
@ -801,6 +802,9 @@ pub struct DeviceManager {
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
id_to_dev_info: HashMap<(DeviceType, String), MMIODeviceInfo>,
|
||||
|
||||
// seccomp action
|
||||
seccomp_action: SeccompAction,
|
||||
}
|
||||
|
||||
impl DeviceManager {
|
||||
@ -811,6 +815,7 @@ impl DeviceManager {
|
||||
_exit_evt: &EventFd,
|
||||
#[cfg_attr(target_arch = "aarch64", allow(unused_variables))] reset_evt: &EventFd,
|
||||
vmm_path: PathBuf,
|
||||
seccomp_action: SeccompAction,
|
||||
) -> DeviceManagerResult<Arc<Mutex<Self>>> {
|
||||
let device_tree = Arc::new(Mutex::new(DeviceTree::new()));
|
||||
|
||||
@ -872,6 +877,7 @@ impl DeviceManager {
|
||||
reset_evt: reset_evt.try_clone().map_err(DeviceManagerError::EventFd)?,
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
id_to_dev_info: HashMap::new(),
|
||||
seccomp_action,
|
||||
};
|
||||
|
||||
#[cfg(feature = "acpi")]
|
||||
@ -1710,6 +1716,7 @@ impl DeviceManager {
|
||||
disk_cfg.iommu,
|
||||
disk_cfg.num_queues,
|
||||
disk_cfg.queue_size,
|
||||
self.seccomp_action.clone(),
|
||||
)
|
||||
.map_err(DeviceManagerError::CreateVirtioBlock)?,
|
||||
));
|
||||
@ -1736,6 +1743,7 @@ impl DeviceManager {
|
||||
disk_cfg.iommu,
|
||||
disk_cfg.num_queues,
|
||||
disk_cfg.queue_size,
|
||||
self.seccomp_action.clone(),
|
||||
)
|
||||
.map_err(DeviceManagerError::CreateVirtioBlock)?,
|
||||
));
|
||||
@ -1762,6 +1770,7 @@ impl DeviceManager {
|
||||
disk_cfg.iommu,
|
||||
disk_cfg.num_queues,
|
||||
disk_cfg.queue_size,
|
||||
self.seccomp_action.clone(),
|
||||
)
|
||||
.map_err(DeviceManagerError::CreateVirtioBlock)?,
|
||||
));
|
||||
|
@ -268,7 +268,7 @@ impl Vm {
|
||||
exit_evt: EventFd,
|
||||
reset_evt: EventFd,
|
||||
vmm_path: PathBuf,
|
||||
_seccomp_action: &SeccompAction,
|
||||
seccomp_action: &SeccompAction,
|
||||
hypervisor: Arc<dyn hypervisor::Hypervisor>,
|
||||
_saved_clock: Option<hypervisor::ClockData>,
|
||||
) -> Result<Self> {
|
||||
@ -285,6 +285,7 @@ impl Vm {
|
||||
&exit_evt,
|
||||
&reset_evt,
|
||||
vmm_path,
|
||||
seccomp_action.clone(),
|
||||
)
|
||||
.map_err(Error::DeviceManager)?;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user