mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vmm: Add seccomp filter for migrate-send-postcopy thread
Applying seccomp filtering to the migration postcopy thread running on the source VM during migration. Signed-off-by: Sebastien Boeuf <sboeuf@meta.com> Assisted-by: Claude:claude-opus-4-8
This commit is contained in:
@@ -31,7 +31,7 @@ use libc::{EFD_NONBLOCK, SIGINT, SIGTERM, TCSANOW, tcsetattr, termios};
|
||||
use log::{debug, error, info, trace, warn};
|
||||
use memory_manager::MemoryManagerSnapshotData;
|
||||
use pci::PciBdf;
|
||||
use seccompiler::{SeccompAction, apply_filter};
|
||||
use seccompiler::{BpfProgram, SeccompAction, apply_filter};
|
||||
use serde::ser::{SerializeStruct, Serializer};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use signal_hook::iterator::{Handle, Signals};
|
||||
@@ -1531,6 +1531,7 @@ impl Vmm {
|
||||
hypervisor: &dyn hypervisor::Hypervisor,
|
||||
send_data_migration: &VmSendMigrationData,
|
||||
initial_vm_state: VmState,
|
||||
seccomp_action: &SeccompAction,
|
||||
) -> result::Result<(), MigratableError> {
|
||||
// State machine that is updated with more context as we progress.
|
||||
let mut ctx = OngoingMigrationContext::new();
|
||||
@@ -1667,9 +1668,19 @@ impl Vmm {
|
||||
send_data_migration.tls_dir.as_deref(),
|
||||
)?;
|
||||
let guest_memory = vm.guest_memory();
|
||||
// Build the seccomp filter on the parent thread so any failure aborts
|
||||
// the migration before the serve thread is spawned.
|
||||
let seccomp_filter = get_seccomp_filter(
|
||||
seccomp_action,
|
||||
Thread::MigrateSendPostcopy,
|
||||
None,
|
||||
)
|
||||
.map_err(|e| {
|
||||
MigratableError::MigrateSend(anyhow!("creating postcopy serve seccomp filter: {e}"))
|
||||
})?;
|
||||
let handle = thread::Builder::new()
|
||||
.name("migrate-send-postcopy".to_owned())
|
||||
.spawn(move || Self::serve_postcopy(fault_stream, guest_memory))
|
||||
.spawn(move || Self::serve_postcopy(seccomp_filter, fault_stream, guest_memory))
|
||||
.map_err(|e| {
|
||||
MigratableError::MigrateSend(anyhow!("spawning postcopy serve thread: {e}"))
|
||||
})?;
|
||||
@@ -1751,9 +1762,19 @@ impl Vmm {
|
||||
reason = "runs on a dedicated thread and must own its arguments"
|
||||
)]
|
||||
fn serve_postcopy(
|
||||
seccomp_filter: BpfProgram,
|
||||
mut socket: SocketStream,
|
||||
guest_memory: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
) -> result::Result<(), MigratableError> {
|
||||
// Apply the dedicated seccomp filter for this thread. It is empty when
|
||||
// seccomp is disabled (SeccompAction::Allow), in which case there is
|
||||
// nothing to apply.
|
||||
if !seccomp_filter.is_empty() {
|
||||
apply_filter(&seccomp_filter).map_err(|e| {
|
||||
MigratableError::MigrateSend(anyhow!("applying postcopy serve seccomp filter: {e}"))
|
||||
})?;
|
||||
}
|
||||
|
||||
let mut buf: Vec<u8> = Vec::new();
|
||||
info!("Postcopy: source entering PageFault serve loop");
|
||||
|
||||
@@ -3099,6 +3120,7 @@ impl RequestHandler for Vmm {
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
self.hypervisor.clone(),
|
||||
initial_vm_state,
|
||||
self.seccomp_action.clone(),
|
||||
) {
|
||||
Ok(handle) => {
|
||||
self.vm = VmOwnership::Migration {
|
||||
|
||||
@@ -21,6 +21,7 @@ use std::thread::JoinHandle;
|
||||
|
||||
use event_monitor::event;
|
||||
use log::warn;
|
||||
use seccompiler::SeccompAction;
|
||||
use vm_migration::MigratableError;
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
@@ -75,6 +76,7 @@ pub struct MigrationWorker {
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
hypervisor: Arc<dyn hypervisor::Hypervisor>,
|
||||
initial_vm_state: VmState,
|
||||
seccomp_action: SeccompAction,
|
||||
}
|
||||
|
||||
impl MigrationWorker {
|
||||
@@ -90,6 +92,7 @@ impl MigrationWorker {
|
||||
self.hypervisor.as_ref(),
|
||||
&self.config,
|
||||
self.initial_vm_state,
|
||||
&self.seccomp_action,
|
||||
)
|
||||
.inspect(|_| event!("vm", "migration-finished"))
|
||||
.inspect_err(|_| event!("vm", "migration-failed"));
|
||||
@@ -116,6 +119,7 @@ impl MigrationWorker {
|
||||
dyn hypervisor::Hypervisor,
|
||||
>,
|
||||
initial_vm_state: VmState,
|
||||
seccomp_action: SeccompAction,
|
||||
) -> Result<MigrationWorkerHandle, MigrationWorkerSpawnError> {
|
||||
let (vm_sender, vm_receiver) = std::sync::mpsc::sync_channel(0);
|
||||
let worker = MigrationWorker {
|
||||
@@ -125,6 +129,7 @@ impl MigrationWorker {
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
hypervisor,
|
||||
initial_vm_state,
|
||||
seccomp_action,
|
||||
};
|
||||
|
||||
let inner_handle = match thread::Builder::new()
|
||||
|
||||
@@ -42,6 +42,7 @@ pub enum Thread {
|
||||
Vmm,
|
||||
PtyForeground,
|
||||
SerialManager,
|
||||
MigrateSendPostcopy,
|
||||
}
|
||||
|
||||
/// Shorthand for chaining `SeccompCondition`s with the `and` operator in a `SeccompRule`.
|
||||
@@ -1084,6 +1085,35 @@ fn serial_manager_thread_rules() -> Result<Vec<(i64, Vec<SeccompRule>)>, Backend
|
||||
])
|
||||
}
|
||||
|
||||
// The filter containing the white listed syscall rules required by the
|
||||
// migration postcopy thread.
|
||||
fn migrate_send_postcopy_thread_rules() -> Result<Vec<(i64, Vec<SeccompRule>)>, BackendError> {
|
||||
Ok(vec![
|
||||
(libc::SYS_brk, vec![]),
|
||||
(libc::SYS_clock_gettime, vec![]),
|
||||
(libc::SYS_close, vec![]),
|
||||
(libc::SYS_exit, vec![]),
|
||||
(libc::SYS_futex, vec![]),
|
||||
(libc::SYS_getrandom, vec![]),
|
||||
(libc::SYS_gettid, vec![]),
|
||||
(libc::SYS_madvise, vec![]),
|
||||
(libc::SYS_mmap, vec![]),
|
||||
(libc::SYS_mprotect, vec![]),
|
||||
(libc::SYS_munmap, vec![]),
|
||||
(libc::SYS_read, vec![]),
|
||||
(libc::SYS_recvfrom, vec![]),
|
||||
(libc::SYS_recvmsg, vec![]),
|
||||
(libc::SYS_rt_sigprocmask, vec![]),
|
||||
(libc::SYS_rt_sigreturn, vec![]),
|
||||
(libc::SYS_sched_yield, vec![]),
|
||||
(libc::SYS_sendmsg, vec![]),
|
||||
(libc::SYS_sendto, vec![]),
|
||||
(libc::SYS_sigaltstack, vec![]),
|
||||
(libc::SYS_write, vec![]),
|
||||
(libc::SYS_writev, vec![]),
|
||||
])
|
||||
}
|
||||
|
||||
fn get_seccomp_rules(
|
||||
thread_type: Thread,
|
||||
hypervisor_type: Option<HypervisorType>,
|
||||
@@ -1102,6 +1132,7 @@ fn get_seccomp_rules(
|
||||
hypervisor_type.expect("hypervisor_type is required for Vmm threads"),
|
||||
)?),
|
||||
Thread::PtyForeground => Ok(pty_foreground_thread_rules()?),
|
||||
Thread::MigrateSendPostcopy => Ok(migrate_send_postcopy_thread_rules()?),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user