Skip to content

Commit 073d5ac

Browse files
JamesC1305ShadowCurse
authored andcommitted
Add seccomp filters to VMM
Add seccompiler filters as a field of the VMM. This is required to ensure that the newly created vCPU threads have the same filters as the currently existing vCPU threads Signed-off-by: James Curtis <[email protected]>
1 parent c3563f6 commit 073d5ac

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

src/vmm/src/builder.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,15 @@ impl std::convert::From<linux_loader::cmdline::Error> for StartMicrovmError {
145145
}
146146

147147
#[cfg_attr(target_arch = "aarch64", allow(unused))]
148+
#[allow(clippy::too_many_arguments)]
148149
fn create_vmm_and_vcpus(
149150
instance_info: &InstanceInfo,
150151
event_manager: &mut EventManager,
151152
guest_memory: GuestMemoryMmap,
152153
uffd: Option<Uffd>,
153154
track_dirty_pages: bool,
154155
vcpu_count: u8,
156+
#[cfg(target_arch = "x86_64")] seccomp_filters: BpfThreadMap,
155157
kvm_capabilities: Vec<KvmCapability>,
156158
) -> Result<(Vmm, Vec<Vcpu>), StartMicrovmError> {
157159
use self::StartMicrovmError::*;
@@ -229,6 +231,8 @@ fn create_vmm_and_vcpus(
229231
uffd,
230232
vcpus_handles: Vec::new(),
231233
vcpus_exit_evt,
234+
#[cfg(target_arch = "x86_64")]
235+
seccomp_filters,
232236
resource_allocator,
233237
mmio_device_manager,
234238
#[cfg(target_arch = "x86_64")]
@@ -309,6 +313,8 @@ pub fn build_microvm_for_boot(
309313
None,
310314
track_dirty_pages,
311315
vm_resources.vm_config.vcpu_count,
316+
#[cfg(target_arch = "x86_64")]
317+
seccomp_filters.clone(),
312318
cpu_template.kvm_capabilities.clone(),
313319
)?;
314320

@@ -478,6 +484,8 @@ pub fn build_microvm_from_snapshot(
478484
uffd,
479485
vm_resources.vm_config.track_dirty_pages,
480486
vm_resources.vm_config.vcpu_count,
487+
#[cfg(target_arch = "x86_64")]
488+
seccomp_filters.clone(),
481489
microvm_state.vm_state.kvm_cap_modifiers.clone(),
482490
)?;
483491

@@ -1155,6 +1163,8 @@ pub mod tests {
11551163
uffd: None,
11561164
vcpus_handles: Vec::new(),
11571165
vcpus_exit_evt,
1166+
#[cfg(target_arch = "x86_64")]
1167+
seccomp_filters: crate::seccomp_filters::get_empty_filters(),
11581168
resource_allocator: ResourceAllocator::new().unwrap(),
11591169
mmio_device_manager,
11601170
#[cfg(target_arch = "x86_64")]

src/vmm/src/lib.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,17 @@ use device_manager::resources::ResourceAllocator;
124124
use devices::acpi::vmgenid::VmGenIdError;
125125
use event_manager::{EventManager as BaseEventManager, EventOps, Events, MutEventSubscriber};
126126
use seccompiler::BpfProgram;
127+
#[cfg(target_arch = "x86_64")]
128+
use seccompiler::BpfThreadMap;
127129
use userfaultfd::Uffd;
128130
use utils::epoll::EventSet;
129131
use utils::eventfd::EventFd;
130132
use utils::terminal::Terminal;
131133
use utils::u64_to_usize;
134+
#[cfg(target_arch = "x86_64")]
135+
use vmm_config::hotplug::{HotplugVcpuConfig, HotplugVcpuError};
136+
#[cfg(target_arch = "x86_64")]
137+
use vmm_config::machine_config::{MachineConfigUpdate, MAX_SUPPORTED_VCPUS};
132138
use vstate::vcpu::{self, KvmVcpuConfigureError, StartThreadedError, VcpuSendEventError};
133139

134140
use crate::arch::DeviceType;
@@ -317,6 +323,9 @@ pub struct Vmm {
317323
vcpus_handles: Vec<VcpuHandle>,
318324
// Used by Vcpus and devices to initiate teardown; Vmm should never write here.
319325
vcpus_exit_evt: EventFd,
326+
// seccomp_filters are only needed in VMM for hotplugging vCPUS.
327+
#[cfg(target_arch = "x86_64")]
328+
seccomp_filters: BpfThreadMap,
320329

321330
// Allocator for guest resrouces
322331
resource_allocator: ResourceAllocator,
@@ -600,6 +609,66 @@ impl Vmm {
600609
Ok(cpu_configs)
601610
}
602611

612+
/// Adds new vCPUs to VMM.
613+
#[cfg(target_arch = "x86_64")]
614+
pub fn hotplug_vcpus(
615+
&mut self,
616+
config: HotplugVcpuConfig,
617+
) -> Result<MachineConfigUpdate, HotplugVcpuError> {
618+
use crate::logger::IncMetric;
619+
if config.vcpu_count < 1 {
620+
return Err(HotplugVcpuError::VcpuCountTooLow);
621+
} else if self
622+
.vcpus_handles
623+
.len()
624+
.checked_add(config.vcpu_count.into())
625+
.ok_or(HotplugVcpuError::VcpuCountTooHigh)?
626+
> MAX_SUPPORTED_VCPUS.into()
627+
{
628+
return Err(HotplugVcpuError::VcpuCountTooHigh);
629+
}
630+
631+
// Create and start new vcpus
632+
let mut vcpus = Vec::with_capacity(config.vcpu_count.into());
633+
634+
#[allow(clippy::cast_possible_truncation)]
635+
let start_idx = self.vcpus_handles.len().try_into().unwrap();
636+
for cpu_idx in start_idx..(start_idx + config.vcpu_count) {
637+
let exit_evt = self
638+
.vcpus_exit_evt
639+
.try_clone()
640+
.map_err(HotplugVcpuError::EventFd)?;
641+
let vcpu =
642+
Vcpu::new(cpu_idx, &self.vm, exit_evt).map_err(HotplugVcpuError::VcpuCreate)?;
643+
vcpus.push(vcpu);
644+
}
645+
646+
self.start_vcpus(
647+
vcpus,
648+
self.seccomp_filters
649+
.get("vcpu")
650+
.ok_or_else(|| HotplugVcpuError::MissingSeccompFilters("vcpu".to_string()))?
651+
.clone(),
652+
)
653+
.map_err(HotplugVcpuError::VcpuStart)?;
654+
655+
#[allow(clippy::cast_lossless)]
656+
METRICS.hotplug.vcpus_added.add(config.vcpu_count.into());
657+
658+
// Update VM config to reflect new CPUs added
659+
#[allow(clippy::cast_possible_truncation)]
660+
let new_machine_config = MachineConfigUpdate {
661+
vcpu_count: Some(self.vcpus_handles.len() as u8),
662+
mem_size_mib: None,
663+
smt: None,
664+
cpu_template: None,
665+
track_dirty_pages: None,
666+
huge_pages: None,
667+
};
668+
669+
Ok(new_machine_config)
670+
}
671+
603672
/// Retrieves the KVM dirty bitmap for each of the guest's memory regions.
604673
pub fn reset_dirty_bitmap(&self) {
605674
self.guest_memory

0 commit comments

Comments
 (0)