mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-10-21 11:58:41 +00:00
dragonball: add seccomp support for dragonball
This commit modifies seccomp framework to support different restrictions for different threads. Signed-off-by: wangxinge <wangxinge@bupt.edu.cn>
This commit is contained in:
10
src/dragonball/Cargo.lock
generated
10
src/dragonball/Cargo.lock
generated
@@ -344,20 +344,26 @@ name = "dbs-pci"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"dbs-address-space",
|
||||
"dbs-allocator",
|
||||
"dbs-arch",
|
||||
"dbs-boot",
|
||||
"dbs-device",
|
||||
"dbs-interrupt",
|
||||
"dbs-utils",
|
||||
"dbs-virtio-devices",
|
||||
"downcast-rs",
|
||||
"kvm-bindings",
|
||||
"kvm-ioctls",
|
||||
"libc",
|
||||
"log",
|
||||
"serde",
|
||||
"thiserror 1.0.48",
|
||||
"vfio-bindings",
|
||||
"vfio-ioctls",
|
||||
"virtio-queue",
|
||||
"vm-memory",
|
||||
"vmm-sys-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1810,9 +1816,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "seccompiler"
|
||||
version = "0.2.0"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e01d1292a1131b22ccea49f30bd106f1238b5ddeec1a98d39268dcc31d540e68"
|
||||
checksum = "a4ae55de56877481d112a559bbc12667635fdaf5e005712fd4e2b2fa50ffc884"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
@@ -33,7 +33,7 @@ event-manager = "0.2.1"
|
||||
kvm-bindings = "0.6.0"
|
||||
kvm-ioctls = "0.12.0"
|
||||
linux-loader = "0.8.0"
|
||||
seccompiler = "0.2.0"
|
||||
seccompiler = "0.5.0"
|
||||
vfio-bindings = "0.3.0"
|
||||
vfio-ioctls = "0.1.0"
|
||||
virtio-bindings = "0.1.0"
|
||||
|
@@ -479,14 +479,13 @@ impl VmmService {
|
||||
use self::StartMicroVmError::MicroVMAlreadyRunning;
|
||||
use self::VmmActionError::StartMicroVm;
|
||||
|
||||
let vmm_seccomp_filter = vmm.vmm_seccomp_filter();
|
||||
let vcpu_seccomp_filter = vmm.vcpu_seccomp_filter();
|
||||
let seccomp_filters = vmm.seccomp_filters();
|
||||
let vm = vmm.get_vm_mut().ok_or(VmmActionError::InvalidVMID)?;
|
||||
if vm.is_vm_initialized() {
|
||||
return Err(StartMicroVm(MicroVMAlreadyRunning));
|
||||
}
|
||||
|
||||
vm.start_microvm(event_mgr, vmm_seccomp_filter, vcpu_seccomp_filter)
|
||||
vm.start_microvm(event_mgr, seccomp_filters)
|
||||
.map(|_| VmmData::Empty)
|
||||
.map_err(StartMicroVm)
|
||||
}
|
||||
|
@@ -219,6 +219,10 @@ pub enum StartMicroVmError {
|
||||
/// Failed to register DMA memory address range.
|
||||
#[error("failure while registering DMA address range: {0:?}")]
|
||||
RegisterDMAAddress(#[source] VfioDeviceError),
|
||||
|
||||
/// Cannot build seccomp filters.
|
||||
#[error("failure while configuring seccomp filters: {0}")]
|
||||
SeccompFilters(#[source] seccompiler::Error),
|
||||
}
|
||||
|
||||
/// Errors associated with starting the instance.
|
||||
|
@@ -48,7 +48,7 @@ mod vmm;
|
||||
|
||||
pub use self::error::StartMicroVmError;
|
||||
pub use self::io_manager::IoManagerCached;
|
||||
pub use self::vmm::Vmm;
|
||||
pub use self::vmm::{Vmm, ALL_THREADS, VCPU_THREAD, VMM_THREAD};
|
||||
|
||||
/// Success exit code.
|
||||
pub const EXIT_CODE_OK: u8 = 0;
|
||||
|
@@ -1,6 +1,7 @@
|
||||
// Copyright (C) 2021 Alibaba Cloud. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::io::{self, Read, Seek, SeekFrom};
|
||||
use std::ops::Deref;
|
||||
use std::os::unix::io::RawFd;
|
||||
@@ -18,6 +19,7 @@ use dbs_utils::time::TimestampUs;
|
||||
use kvm_ioctls::VmFd;
|
||||
use linux_loader::loader::{KernelLoader, KernelLoaderResult};
|
||||
use seccompiler::BpfProgram;
|
||||
use seccompiler::{apply_filter_all_threads, Error as SecError};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use slog::{error, info};
|
||||
use vm_memory::{Bytes, GuestAddress, GuestAddressSpace};
|
||||
@@ -42,6 +44,7 @@ use crate::resource_manager::ResourceManager;
|
||||
use crate::vcpu::{VcpuManager, VcpuManagerError};
|
||||
#[cfg(feature = "hotplug")]
|
||||
use crate::vcpu::{VcpuResizeError, VcpuResizeInfo};
|
||||
use crate::{ALL_THREADS, VCPU_THREAD, VMM_THREAD};
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use dbs_arch::gic::Error as GICError;
|
||||
|
||||
@@ -709,10 +712,27 @@ impl Vm {
|
||||
pub fn start_microvm(
|
||||
&mut self,
|
||||
event_mgr: &mut EventManager,
|
||||
vmm_seccomp_filter: BpfProgram,
|
||||
vcpu_seccomp_filter: BpfProgram,
|
||||
seccomp_filters: HashMap<String, BpfProgram>,
|
||||
) -> std::result::Result<(), StartMicroVmError> {
|
||||
info!(self.logger, "VM: received instance start command");
|
||||
|
||||
if let Some(process_seccomp_filter) = seccomp_filters.get(ALL_THREADS) {
|
||||
// Load seccomp filters for the whole process.
|
||||
// Execution panics if filters cannot be loaded, use --seccomp-level=0 if skipping filters
|
||||
// altogether is the desired behaviour.
|
||||
if let Err(e) = apply_filter_all_threads(process_seccomp_filter) {
|
||||
if !matches!(e, SecError::EmptyFilter) {
|
||||
error!(
|
||||
self.logger,
|
||||
"VM: failed to apply process-wide seccomp filters: {}", e
|
||||
);
|
||||
return Err(StartMicroVmError::SeccompFilters(e));
|
||||
}
|
||||
} else {
|
||||
info!(self.logger, "VM: process-wide seccomp filters applied");
|
||||
}
|
||||
}
|
||||
|
||||
if self.is_vm_initialized() {
|
||||
return Err(StartMicroVmError::MicroVMAlreadyRunning);
|
||||
}
|
||||
@@ -738,8 +758,14 @@ impl Vm {
|
||||
AddressManagerError::GuestMemoryNotInitialized,
|
||||
))?;
|
||||
|
||||
self.init_vcpu_manager(vm_as.clone(), vcpu_seccomp_filter)
|
||||
.map_err(StartMicroVmError::Vcpu)?;
|
||||
self.init_vcpu_manager(
|
||||
vm_as.clone(),
|
||||
seccomp_filters
|
||||
.get(VCPU_THREAD)
|
||||
.cloned()
|
||||
.unwrap_or_default(),
|
||||
)
|
||||
.map_err(StartMicroVmError::Vcpu)?;
|
||||
self.init_microvm(event_mgr.epoll_manager(), vm_as.clone(), request_ts)?;
|
||||
self.init_configure_system(&vm_as)?;
|
||||
#[cfg(feature = "dbs-upcall")]
|
||||
@@ -751,7 +777,7 @@ impl Vm {
|
||||
info!(self.logger, "VM: start vcpus");
|
||||
self.vcpu_manager()
|
||||
.map_err(StartMicroVmError::Vcpu)?
|
||||
.start_boot_vcpus(vmm_seccomp_filter)
|
||||
.start_boot_vcpus(seccomp_filters.get(VMM_THREAD).cloned().unwrap_or_default())
|
||||
.map_err(StartMicroVmError::Vcpu)?;
|
||||
|
||||
// Use expect() to crash if the other thread poisoned this lock.
|
||||
|
@@ -6,6 +6,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the THIRD-PARTY file.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Formatter;
|
||||
use std::os::unix::io::RawFd;
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
@@ -22,6 +23,19 @@ use crate::event_manager::{EventContext, EventManager};
|
||||
use crate::vm::Vm;
|
||||
use crate::{EXIT_CODE_GENERIC_ERROR, EXIT_CODE_OK};
|
||||
|
||||
// Thread types to which the seccomp restrictions apply
|
||||
// Currently the restrictions are applied to the whole process
|
||||
// More thread types can be added later to accommodate more granular constraints.
|
||||
|
||||
/// Union of restrictions for all threads;
|
||||
/// The corresponding restrictions are applied to the whole process
|
||||
/// This type should be used with any other thread type which has specific restrictions
|
||||
pub const ALL_THREADS: &str = "all";
|
||||
/// VMM thread
|
||||
pub const VMM_THREAD: &str = "vmm";
|
||||
/// Vcpu thread
|
||||
pub const VCPU_THREAD: &str = "vcpu";
|
||||
|
||||
/// Global coordinator to manage API servers, virtual machines, upgrade etc.
|
||||
///
|
||||
/// Originally firecracker assumes an VMM only manages an VM, and doesn't distinguish VMM and VM.
|
||||
@@ -41,8 +55,7 @@ pub struct Vmm {
|
||||
// Will change to a HashMap when enabling 1 VMM with multiple VMs.
|
||||
vm: Vm,
|
||||
|
||||
vcpu_seccomp_filter: BpfProgram,
|
||||
vmm_seccomp_filter: BpfProgram,
|
||||
seccomp_filters: HashMap<String, BpfProgram>,
|
||||
}
|
||||
|
||||
impl Vmm {
|
||||
@@ -50,8 +63,7 @@ impl Vmm {
|
||||
pub fn new(
|
||||
api_shared_info: Arc<RwLock<InstanceInfo>>,
|
||||
api_event_fd: EventFd,
|
||||
vmm_seccomp_filter: BpfProgram,
|
||||
vcpu_seccomp_filter: BpfProgram,
|
||||
seccomp_filters: HashMap<String, BpfProgram>,
|
||||
kvm_fd: Option<RawFd>,
|
||||
) -> Result<Self> {
|
||||
let epoll_manager = EpollManager::default();
|
||||
@@ -59,8 +71,7 @@ impl Vmm {
|
||||
api_shared_info,
|
||||
api_event_fd,
|
||||
epoll_manager,
|
||||
vmm_seccomp_filter,
|
||||
vcpu_seccomp_filter,
|
||||
seccomp_filters,
|
||||
kvm_fd,
|
||||
)
|
||||
}
|
||||
@@ -70,8 +81,7 @@ impl Vmm {
|
||||
api_shared_info: Arc<RwLock<InstanceInfo>>,
|
||||
api_event_fd: EventFd,
|
||||
epoll_manager: EpollManager,
|
||||
vmm_seccomp_filter: BpfProgram,
|
||||
vcpu_seccomp_filter: BpfProgram,
|
||||
seccomp_filters: HashMap<String, BpfProgram>,
|
||||
kvm_fd: Option<RawFd>,
|
||||
) -> Result<Self> {
|
||||
let vm = Vm::new(kvm_fd, api_shared_info, epoll_manager.clone())?;
|
||||
@@ -81,8 +91,7 @@ impl Vmm {
|
||||
event_ctx,
|
||||
epoll_manager,
|
||||
vm,
|
||||
vcpu_seccomp_filter,
|
||||
vmm_seccomp_filter,
|
||||
seccomp_filters,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -96,14 +105,9 @@ impl Vmm {
|
||||
Some(&mut self.vm)
|
||||
}
|
||||
|
||||
/// Get the seccomp rules for vCPU threads.
|
||||
pub fn vcpu_seccomp_filter(&self) -> BpfProgram {
|
||||
self.vcpu_seccomp_filter.clone()
|
||||
}
|
||||
|
||||
/// Get the seccomp rules for VMM threads.
|
||||
pub fn vmm_seccomp_filter(&self) -> BpfProgram {
|
||||
self.vmm_seccomp_filter.clone()
|
||||
/// Get all seccomp rules.
|
||||
pub fn seccomp_filters(&self) -> HashMap<String, BpfProgram> {
|
||||
self.seccomp_filters.clone()
|
||||
}
|
||||
|
||||
/// Run the event loop to service API requests.
|
||||
@@ -206,14 +210,15 @@ impl std::fmt::Debug for Vmm {
|
||||
f.debug_struct("Vmm")
|
||||
.field("event_ctx", &self.event_ctx)
|
||||
.field("vm", &self.vm.shared_info())
|
||||
.field("vcpu_seccomp_filter", &self.vcpu_seccomp_filter)
|
||||
.field("vmm_seccomp_filter", &self.vmm_seccomp_filter)
|
||||
.field("seccomp_filters", &self.seccomp_filters)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests {
|
||||
use std::collections::HashMap;
|
||||
|
||||
use test_utils::skip_if_not_root;
|
||||
|
||||
use super::*;
|
||||
@@ -221,17 +226,8 @@ pub(crate) mod tests {
|
||||
pub fn create_vmm_instance(epoll_manager: EpollManager) -> Vmm {
|
||||
let info = Arc::new(RwLock::new(InstanceInfo::default()));
|
||||
let event_fd = EventFd::new(libc::EFD_NONBLOCK).unwrap();
|
||||
let seccomp_filter: BpfProgram = Vec::new();
|
||||
|
||||
Vmm::new_with_epoll_manager(
|
||||
info,
|
||||
event_fd,
|
||||
epoll_manager,
|
||||
seccomp_filter.clone(),
|
||||
seccomp_filter,
|
||||
None,
|
||||
)
|
||||
.unwrap()
|
||||
Vmm::new_with_epoll_manager(info, event_fd, epoll_manager, HashMap::new(), None).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
Reference in New Issue
Block a user