Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions src/firecracker/src/api_server_adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,13 @@ impl ApiServerAdapter {
to_api: Sender<ApiResponse>,
vmm: Arc<Mutex<Vmm>>,
event_manager: &mut EventManager,
seccomp_filters: &BpfThreadMap,
) -> Result<(), ApiServerError> {
let api_adapter = Arc::new(Mutex::new(Self {
api_event_fd,
from_api,
to_api,
controller: RuntimeApiController::new(vmm.clone()),
controller: RuntimeApiController::new(vmm.clone(), seccomp_filters),
request: None,
}));
event_manager.add_subscriber(api_adapter.clone());
Expand Down Expand Up @@ -262,7 +263,14 @@ pub(crate) fn run_with_api(
.expect("Poisoned lock")
.start(super::metrics::WRITE_METRICS_PERIOD_MS);

ApiServerAdapter::run_microvm(api_event_fd, from_api, to_api, vmm, &mut event_manager)
ApiServerAdapter::run_microvm(
api_event_fd,
from_api,
to_api,
vmm,
&mut event_manager,
seccomp_filters,
)
});

api_kill_switch.write(1).unwrap();
Expand Down
15 changes: 15 additions & 0 deletions src/vmm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use crate::device_manager::{
DeviceRestoreArgs,
};
use crate::devices::virtio::balloon::Balloon;
use crate::devices::virtio::block::BlockError;
use crate::devices::virtio::block::device::Block;
use crate::devices::virtio::device::VirtioDevice;
use crate::devices::virtio::mem::{VIRTIO_MEM_DEFAULT_SLOT_SIZE_MIB, VirtioMem};
Expand Down Expand Up @@ -109,6 +110,8 @@ pub enum StartMicrovmError {
NetDeviceNotConfigured,
/// Cannot open the block device backing file: {0}
OpenBlockDevice(io::Error),
/// Failed to spawn the block worker thread: {0}
SpawnBlockWorker(BlockError),
/// Cannot restore microvm state: {0}
RestoreMicrovmState(MicrovmStateError),
/// Cannot set vm resources: {0}
Expand Down Expand Up @@ -238,6 +241,7 @@ pub fn build_microvm_for_boot(
&mut boot_cmdline,
vm_resources.block.devices.iter(),
event_manager,
seccomp_filters,
)?;
attach_net_devices(
&mut device_manager,
Expand Down Expand Up @@ -502,6 +506,7 @@ pub fn build_microvm_from_snapshot(
vm_resources,
instance_id: &instance_info.id,
vcpus_exit_evt: kvm_vm.vcpus_exit_evt(),
seccomp_filters,
};
#[allow(unused_mut)]
let mut device_manager =
Expand Down Expand Up @@ -659,6 +664,7 @@ fn attach_block_devices<'a, I: Iterator<Item = &'a Arc<Mutex<Block>>> + Debug>(
cmdline: &mut LoaderKernelCmdline,
blocks: I,
event_manager: &mut EventManager,
seccomp_filters: &BpfThreadMap,
) -> Result<(), StartMicrovmError> {
for block in blocks {
let (id, is_vhost_user) = {
Expand All @@ -672,6 +678,13 @@ fn attach_block_devices<'a, I: Iterator<Item = &'a Arc<Mutex<Block>>> + Debug>(
}
(locked.id().to_string(), locked.is_vhost_user())
};

block
.lock()
.expect("Poisoned lock")
.spawn_worker(seccomp_filters.get("blk_worker").cloned())
.map_err(StartMicrovmError::SpawnBlockWorker)?;

// The device mutex mustn't be locked here otherwise it will deadlock.
device_manager.attach_boot_virtio_device(
vm,
Expand Down Expand Up @@ -778,6 +791,7 @@ pub(crate) mod tests {
use crate::devices::virtio::vsock::VSOCK_DEV_ID;
use crate::mmds::data_store::{Mmds, MmdsVersion};
use crate::mmds::ns::MmdsNetworkStack;
use crate::seccomp::get_empty_filters;
use crate::utils::mib_to_bytes;
use crate::vmm_config::balloon::{BALLOON_DEV_ID, BalloonBuilder, BalloonDeviceConfig};
use crate::vmm_config::boot_source::BootSourceConfig;
Expand Down Expand Up @@ -917,6 +931,7 @@ pub(crate) mod tests {
cmdline,
block_dev_configs.devices.iter(),
event_manager,
&get_empty_filters(),
)
.unwrap();
block_files
Expand Down
38 changes: 28 additions & 10 deletions src/vmm/src/device_manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ use crate::logger::{error, info};
use crate::rate_limiter::TokenBucket;
use crate::resources::VmResources;
use crate::rpc_interface::VmmActionError;
use crate::seccomp::BpfThreadMap;
use crate::snapshot::Persist;
use crate::utils::open_file_nonblock;
use crate::vmm_config::HotplugDeviceConfig;
Expand Down Expand Up @@ -458,6 +459,7 @@ impl DeviceManager {
vm: Arc<KvmVm>,
config: HotplugDeviceConfig,
event_manager: &mut EventManager,
seccomp_filters: &BpfThreadMap,
) -> Result<(), VmmActionError> {
let dev_type = config.device_type();
let dev_id = config.device_id().to_string();
Expand All @@ -473,7 +475,7 @@ impl DeviceManager {
}

let device = match config {
HotplugDeviceConfig::Block(cfg) => Self::hotplug_make_block(cfg)?,
HotplugDeviceConfig::Block(cfg) => Self::hotplug_make_block(cfg, seccomp_filters)?,
HotplugDeviceConfig::Pmem(cfg) => Self::hotplug_make_pmem(vm.clone(), cfg)?,
HotplugDeviceConfig::Net(cfg) => self.hotplug_make_net(cfg)?,
};
Expand All @@ -488,12 +490,17 @@ impl DeviceManager {

fn hotplug_make_block(
config: BlockDeviceConfig,
seccomp_filters: &BpfThreadMap,
) -> Result<Arc<Mutex<dyn VirtioDevice>>, VmmActionError> {
if config.is_root_device {
return Err(DriveError::RootBlockDeviceAlreadyAdded.into());
}

let block = Block::new(config).map_err(DriveError::CreateBlockDevice)?;
let mut block = Block::new(config).map_err(DriveError::CreateBlockDevice)?;
block
.spawn_worker(seccomp_filters.get("blk_worker").cloned())
.map_err(DriveError::CreateBlockDevice)?;

Ok(Arc::new(Mutex::new(block)))
}

Expand Down Expand Up @@ -673,6 +680,7 @@ pub struct DeviceRestoreArgs<'a> {
pub vcpus_exit_evt: &'a EventFd,
pub vm_resources: &'a mut VmResources,
pub instance_id: &'a str,
pub seccomp_filters: &'a BpfThreadMap,
}

impl std::fmt::Debug for DeviceRestoreArgs<'_> {
Expand Down Expand Up @@ -745,6 +753,7 @@ impl<'a> Persist<'a> for DeviceManager {
vm_resources: constructor_args.vm_resources,
instance_id: constructor_args.instance_id,
event_manager: constructor_args.event_manager,
seccomp_filters: constructor_args.seccomp_filters,
};
let pci_devices = PciDevices::restore(pci_ctor_args, pci_state)
.map_err(DeviceManagerPersistError::PciRestore)?;
Expand All @@ -757,6 +766,7 @@ impl<'a> Persist<'a> for DeviceManager {
event_manager: constructor_args.event_manager,
vm_resources: constructor_args.vm_resources,
instance_id: constructor_args.instance_id,
seccomp_filters: constructor_args.seccomp_filters,
};
let mmio_virtio_devices = MMIOVirtioDevices::restore(mmio_ctor_args, mmio_state)
.map_err(DeviceManagerPersistError::MmioRestore)?;
Expand Down Expand Up @@ -787,6 +797,7 @@ pub(crate) mod tests {
use crate::devices::acpi::vmgenid::VmGenId;
use crate::devices::virtio::block::CacheType;
use crate::rpc_interface::VmmActionError;
use crate::seccomp::get_empty_filters;
use crate::vmm_config::HotplugDeviceConfig;
use crate::vmm_config::drive::{BlockDeviceConfig, DriveError};
use crate::vmm_config::net::{NetworkInterfaceConfig, NetworkInterfaceError};
Expand Down Expand Up @@ -920,12 +931,14 @@ pub(crate) mod tests {
#[test]
fn test_hotplug_block() {
let mut evt_manager = EventManager::new().unwrap();
let seccomp_filters = get_empty_filters();
let mut vmm = default_vmm_with_pci();
let f = TempFile::new().unwrap();

// Successful case
let cfg = HotplugDeviceConfig::Block(make_hotplug_block_cfg("block0", &f, false));
vmm.hotplug_device(cfg, &mut evt_manager).unwrap();
vmm.hotplug_device(cfg, &mut evt_manager, &seccomp_filters)
.unwrap();
assert!(
pci_devices(&vmm.device_manager)
.virtio_devices
Expand All @@ -935,14 +948,14 @@ pub(crate) mod tests {
// Duplicate device ID is rejected
let cfg2 = HotplugDeviceConfig::Block(make_hotplug_block_cfg("block0", &f, false));
assert!(matches!(
vmm.hotplug_device(cfg2, &mut evt_manager),
vmm.hotplug_device(cfg2, &mut evt_manager, &seccomp_filters),
Err(VmmActionError::DeviceIdInUse)
));

// Root block device is rejected
let cfg3 = HotplugDeviceConfig::Block(make_hotplug_block_cfg("block1", &f, true));
assert!(matches!(
vmm.hotplug_device(cfg3, &mut evt_manager),
vmm.hotplug_device(cfg3, &mut evt_manager, &seccomp_filters),
Err(VmmActionError::DriveConfig(
DriveError::RootBlockDeviceAlreadyAdded
))
Expand Down Expand Up @@ -970,11 +983,12 @@ pub(crate) mod tests {
fn test_hotplug_pci_not_enabled() {
let mut vmm = default_vmm();
let mut evt_manager = EventManager::new().unwrap();
let seccomp_filters = get_empty_filters();
let f = TempFile::new().unwrap();

let cfg = HotplugDeviceConfig::Block(make_hotplug_block_cfg("block0", &f, false));
assert!(matches!(
vmm.hotplug_device(cfg, &mut evt_manager),
vmm.hotplug_device(cfg, &mut evt_manager, &seccomp_filters),
Err(VmmActionError::PciNotEnabled)
));
}
Expand Down Expand Up @@ -1007,6 +1021,7 @@ pub(crate) mod tests {
fn test_hotplug_pmem() {
let mut vmm = default_vmm_with_pci();
let mut evt_manager = EventManager::new().unwrap();
let seccomp_filters = get_empty_filters();
let f = TempFile::new().unwrap();
f.as_file().set_len(0x1000).unwrap();

Expand All @@ -1018,7 +1033,8 @@ pub(crate) mod tests {
read_only: false,
..Default::default()
});
vmm.hotplug_device(cfg, &mut evt_manager).unwrap();
vmm.hotplug_device(cfg, &mut evt_manager, &seccomp_filters)
.unwrap();
assert!(
pci_devices(&vmm.device_manager)
.virtio_devices
Expand All @@ -1035,7 +1051,7 @@ pub(crate) mod tests {
..Default::default()
});
assert!(matches!(
vmm.hotplug_device(cfg2, &mut evt_manager),
vmm.hotplug_device(cfg2, &mut evt_manager, &seccomp_filters),
Err(VmmActionError::PmemConfig(
PmemConfigError::AddingSecondRootDevice
))
Expand Down Expand Up @@ -1063,6 +1079,7 @@ pub(crate) mod tests {
fn test_hotplug_net() {
let mut vmm = default_vmm_with_pci();
let mut evt_manager = EventManager::new().unwrap();
let seccomp_filters = get_empty_filters();

let mac = "AA:FC:00:00:00:01";

Expand All @@ -1075,7 +1092,8 @@ pub(crate) mod tests {
rx_rate_limiter: None,
tx_rate_limiter: None,
});
vmm.hotplug_device(cfg, &mut evt_manager).unwrap();
vmm.hotplug_device(cfg, &mut evt_manager, &seccomp_filters)
.unwrap();
assert!(
pci_devices(&vmm.device_manager)
.virtio_devices
Expand All @@ -1092,7 +1110,7 @@ pub(crate) mod tests {
tx_rate_limiter: None,
});
assert!(matches!(
vmm.hotplug_device(cfg2, &mut evt_manager),
vmm.hotplug_device(cfg2, &mut evt_manager, &seccomp_filters),
Err(VmmActionError::NetworkConfig(
NetworkInterfaceError::GuestMacAddressInUse(_)
))
Expand Down
9 changes: 9 additions & 0 deletions src/vmm/src/device_manager/pci_mngr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ use crate::logger::{debug, warn};
use crate::pci::PciSBDF;
use crate::pci::bus::PciRootError;
use crate::resources::VmResources;
use crate::seccomp::BpfThreadMap;
use crate::snapshot::Persist;
use crate::vmm_config::memory_hotplug::MemoryHotplugConfig;
use crate::vstate::bus::BusError;
Expand Down Expand Up @@ -327,6 +328,7 @@ pub struct PciDevicesConstructorArgs<'a> {
pub vm_resources: &'a mut VmResources,
pub instance_id: &'a str,
pub event_manager: &'a mut EventManager,
pub seccomp_filters: &'a BpfThreadMap,
}

impl<'a> Debug for PciDevicesConstructorArgs<'a> {
Expand Down Expand Up @@ -518,6 +520,11 @@ impl<'a> Persist<'a> for PciDevices {
&block_state.device_state,
)?));

device
.lock()
.expect("Poisoned lock")
.spawn_worker(constructor_args.seccomp_filters.get("blk_worker").cloned())?;

constructor_args
.vm_resources
.block
Expand Down Expand Up @@ -685,6 +692,7 @@ mod tests {
use crate::devices::virtio::block::CacheType;
use crate::mmds::data_store::MmdsVersion;
use crate::resources::VmmConfig;
use crate::seccomp::get_empty_filters;
use crate::vmm_config::balloon::BalloonDeviceConfig;
use crate::vmm_config::entropy::EntropyDeviceConfig;
use crate::vmm_config::memory_hotplug::MemoryHotplugConfig;
Expand Down Expand Up @@ -812,6 +820,7 @@ mod tests {
vm_resources,
instance_id: "microvm-id",
event_manager: &mut event_manager,
seccomp_filters: &get_empty_filters(),
};
let _restored_dev_manager = PciDevices::restore(restore_args, pci_state).unwrap();

Expand Down
9 changes: 9 additions & 0 deletions src/vmm/src/device_manager/persist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ use crate::devices::virtio::vsock::persist::{
use crate::devices::virtio::vsock::{Vsock, VsockUnixBackend};
use crate::mmds::data_store::MmdsVersion;
use crate::resources::VmResources;
use crate::seccomp::BpfThreadMap;
use crate::snapshot::Persist;
use crate::vmm_config::memory_hotplug::MemoryHotplugConfig;
use crate::vstate::memory::GuestMemoryMmap;
Expand Down Expand Up @@ -137,6 +138,7 @@ pub struct MMIODevManagerConstructorArgs<'a> {
pub event_manager: &'a mut EventManager,
pub vm_resources: &'a mut VmResources,
pub instance_id: &'a str,
pub seccomp_filters: &'a BpfThreadMap,
}

pub struct MMIOPlatformDevicesConstructorArgs<'a> {
Expand Down Expand Up @@ -479,6 +481,11 @@ impl<'a> Persist<'a> for MMIOVirtioDevices {
&block_state.device_state,
)?));

device
.lock()
.expect("Poisoned lock")
.spawn_worker(constructor_args.seccomp_filters.get("blk_worker").cloned())?;

constructor_args
.vm_resources
.block
Expand Down Expand Up @@ -649,6 +656,7 @@ mod tests {
use crate::device_manager;
use crate::devices::virtio::block::CacheType;
use crate::resources::VmmConfig;
use crate::seccomp::get_empty_filters;
use crate::vmm_config::balloon::BalloonDeviceConfig;
use crate::vmm_config::entropy::EntropyDeviceConfig;
use crate::vmm_config::memory_hotplug::MemoryHotplugConfig;
Expand Down Expand Up @@ -806,6 +814,7 @@ mod tests {
event_manager: &mut event_manager,
vm_resources,
instance_id: "microvm-id",
seccomp_filters: &get_empty_filters(),
};
let _restored_dev_manager = MMIOVirtioDevices::restore(restore_args, mmio_state).unwrap();

Expand Down
10 changes: 10 additions & 0 deletions src/vmm/src/devices/virtio/block/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::devices::virtio::queue::{InvalidAvailIdx, QueueConfig, QueueError};
use crate::devices::virtio::transport::VirtioInterrupt;
use crate::impl_device_type;
use crate::rate_limiter::BucketUpdate;
use crate::seccomp::BpfProgram;
use crate::snapshot::Persist;
use crate::vmm_config::drive::BlockDeviceConfig;
use crate::vstate::memory::GuestMemoryMmap;
Expand Down Expand Up @@ -114,6 +115,15 @@ impl Block {
Self::VhostUser(_) => true,
}
}

pub(crate) fn spawn_worker(
&mut self,
_seccomp_filter: Option<Arc<BpfProgram>>,
) -> Result<(), BlockError> {
match self {
Self::Virtio(_) | Self::VhostUser(_) => Ok(()),
}
}
}

impl VirtioDevice for Block {
Expand Down
2 changes: 2 additions & 0 deletions src/vmm/src/devices/virtio/block/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ pub enum BlockError {
InvalidBlockBackend,
/// Can not restore any backend.
BackendRestore,
/// Missing block worker seccomp filter.
MissingSeccompFilter,
/// Virtio backend error: {0}
VirtioBackend(VirtioBlockError),
/// Vhost user backend error: {0}
Expand Down
Loading
Loading