vmm: migration seccomp: add for migration worker (coordinator thread)

On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This commit is contained in:
Philipp Schuster
2026-06-24 21:37:44 +02:00
committed by Bo Chen
parent b5c028c286
commit fd88e23ecb
3 changed files with 103 additions and 14 deletions

View File

@@ -3152,6 +3152,13 @@ impl RequestHandler for Vmm {
// - this simplifies the code (especially error propagation)
// - the overhead is negligible
let seccomp_filters = {
let worker = get_seccomp_filter(&self.seccomp_action, Thread::MigrationWorker, None)
.map_err(|e| {
MigratableError::MigrateSend(anyhow!(
"Error creating migration seccomp filter: {e}"
))
})?;
let postcopy_server =
get_seccomp_filter(&self.seccomp_action, Thread::MigrateSendPostcopy, None)
.map_err(|e| {
@@ -3160,7 +3167,10 @@ impl RequestHandler for Vmm {
))
})?;
MigrationSeccompFilters { postcopy_server }
MigrationSeccompFilters {
worker,
postcopy_server,
}
};
// Take VM ownership. This also means that API events can no longer

View File

@@ -19,9 +19,10 @@ use std::sync::mpsc::{self, Receiver};
use std::thread::JoinHandle;
use std::{io, thread};
use anyhow::anyhow;
use event_monitor::event;
use log::warn;
use seccompiler::BpfProgram;
use seccompiler::{BpfProgram, apply_filter};
use vm_migration::MigratableError;
use vmm_sys_util::eventfd::EventFd;
@@ -70,6 +71,7 @@ impl Drop for MigrationWorkerHandle {
#[derive(Clone, Debug)]
pub struct MigrationSeccompFilters {
pub worker: BpfProgram,
pub postcopy_server: BpfProgram,
}
@@ -88,26 +90,41 @@ impl MigrationWorker {
/// Drives the migration from its start to its end (success, cancellation,
/// failure)
fn run(self) -> MigrationWorkerResult {
let seccomp_res = if self.seccomp_filters.worker.is_empty() {
Ok(())
} else {
apply_filter(&self.seccomp_filters.worker).map_err(|e| {
MigratableError::MigrateSend(anyhow!(
"Error applying migration seccomp filter: {e}"
))
})
};
let mut vm = self.vm_receiver.recv().expect("VMM should send VM");
event!("vm", "migration-started");
let res = Vmm::send_migration(
&mut vm,
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
self.hypervisor.as_ref(),
&self.config,
self.initial_vm_state,
&self.seccomp_filters,
)
.inspect(|_| event!("vm", "migration-finished"))
.inspect_err(|_| event!("vm", "migration-failed"));
// We can't propagate errors early because of the complex return type,
// therefore we chain the results together.
let migration_result = seccomp_res
.and_then(|()| {
event!("vm", "migration-started");
Vmm::send_migration(
&mut vm,
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
self.hypervisor.as_ref(),
&self.config,
self.initial_vm_state,
&self.seccomp_filters,
)
})
.inspect(|_| event!("vm", "migration-finished"))
.inspect_err(|_| event!("vm", "migration-failed"));
// Notify VMM thread to check migration result.
self.check_migration_evt.write(1).unwrap();
MigrationWorkerResult {
vm,
migration_result: res,
migration_result,
initial_vm_state: self.initial_vm_state,
}
}

View File

@@ -39,6 +39,7 @@ pub enum Thread {
#[cfg(feature = "dbus_api")]
DBusApi,
EventMonitor,
MigrationWorker,
SignalHandler,
Vcpu,
Vmm,
@@ -1063,6 +1064,66 @@ fn event_monitor_thread_rules() -> Result<Vec<(i64, Vec<SeccompRule>)>, BackendE
])
}
fn migration_thread_rules() -> Result<Vec<(i64, Vec<SeccompRule>)>, BackendError> {
Ok(vec![
(libc::SYS_accept4, vec![]),
(libc::SYS_brk, vec![]),
(libc::SYS_clock_gettime, vec![]),
(libc::SYS_clock_nanosleep, vec![]),
(libc::SYS_clone, vec![]),
(libc::SYS_clone3, vec![]),
(libc::SYS_close, vec![]),
(libc::SYS_connect, vec![]),
(libc::SYS_exit, vec![]),
(libc::SYS_exit_group, vec![]),
(libc::SYS_fcntl, vec![]),
(libc::SYS_fstat, vec![]),
(libc::SYS_ftruncate, vec![]),
(libc::SYS_futex, vec![]),
(libc::SYS_getpid, vec![]),
(libc::SYS_getrandom, vec![]),
(libc::SYS_gettid, vec![]),
(libc::SYS_ioctl, vec![]),
(libc::SYS_lseek, vec![]),
(libc::SYS_madvise, vec![]),
(libc::SYS_memfd_create, vec![]),
(libc::SYS_mmap, vec![]),
(libc::SYS_mprotect, vec![]),
(libc::SYS_mremap, vec![]),
(libc::SYS_munmap, vec![]),
(libc::SYS_nanosleep, vec![]),
(libc::SYS_openat, vec![]),
#[cfg(target_arch = "x86_64")]
(libc::SYS_poll, vec![]),
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
(libc::SYS_ppoll, vec![]),
(libc::SYS_prctl, vec![]),
(libc::SYS_read, vec![]),
(libc::SYS_readv, vec![]),
(libc::SYS_tkill, vec![]),
(libc::SYS_recvfrom, vec![]),
(libc::SYS_recvmsg, vec![]),
(libc::SYS_rseq, vec![]),
(libc::SYS_rt_sigprocmask, vec![]),
(libc::SYS_rt_sigreturn, vec![]),
(libc::SYS_sched_getaffinity, vec![]),
(libc::SYS_sched_yield, vec![]),
(libc::SYS_seccomp, vec![]),
(libc::SYS_sendmsg, vec![]),
(libc::SYS_setsockopt, vec![]),
(libc::SYS_sendto, vec![]),
(libc::SYS_set_robust_list, vec![]),
(libc::SYS_sigaltstack, vec![]),
(libc::SYS_socket, vec![]),
(libc::SYS_socketpair, vec![]),
(libc::SYS_statx, vec![]),
(libc::SYS_tgkill, vec![]),
(libc::SYS_timerfd_settime, vec![]),
(libc::SYS_write, vec![]),
(libc::SYS_writev, vec![]),
])
}
fn serial_manager_thread_rules() -> Result<Vec<(i64, Vec<SeccompRule>)>, BackendError> {
Ok(vec![
(libc::SYS_accept4, vec![]),
@@ -1131,6 +1192,7 @@ fn get_seccomp_rules(
#[cfg(feature = "dbus_api")]
Thread::DBusApi => dbus_api_thread_rules()?,
Thread::EventMonitor => event_monitor_thread_rules()?,
Thread::MigrationWorker => migration_thread_rules()?,
Thread::SerialManager => serial_manager_thread_rules()?,
Thread::SignalHandler => signal_handler_thread_rules()?,
Thread::Vcpu => vcpu_thread_rules(