vmm: migration seccomp: add for TCP workers (send and receive)

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:38:04 +02:00
committed by Bo Chen
parent fd88e23ecb
commit 1ae1cc787d
4 changed files with 112 additions and 3 deletions

View File

@@ -980,7 +980,12 @@ impl Vmm {
// The accept thread hands the page fault connection back via this channel.
let (fault_tx, fault_rx) = channel();
let connections = listener.try_clone().and_then(|l| {
ReceiveAdditionalConnections::new(l, guest_memory.clone(), fault_tx)
ReceiveAdditionalConnections::new(
l,
guest_memory.clone(),
fault_tx,
&self.seccomp_action,
)
})?;
Ok(ReceiveMigrationConfiguredData {
memory_manager,
@@ -1652,6 +1657,7 @@ impl Vmm {
send_data_migration.connections,
send_data_migration.tls_dir.as_deref(),
&vm.guest_memory(),
&seccomp_filters.tcp_worker,
)?;
Self::do_memory_migration(
@@ -3159,6 +3165,16 @@ impl RequestHandler for Vmm {
))
})?;
let tcp_worker =
get_seccomp_filter(&self.seccomp_action, Thread::MigrationTcpWorker, None)
.map_err(|e| {
MigratableError::MigrateSend(anyhow!(
"Error creating migration TCP worker seccomp filter: {e}"
))
})?;
// Build the seccomp filter on the parent thread so any failure aborts
// the migration before the serve thread is spawned.
let postcopy_server =
get_seccomp_filter(&self.seccomp_action, Thread::MigrateSendPostcopy, None)
.map_err(|e| {
@@ -3169,6 +3185,7 @@ impl RequestHandler for Vmm {
MigrationSeccompFilters {
worker,
tcp_worker,
postcopy_server,
}
};

View File

@@ -18,6 +18,7 @@ use std::{mem, thread};
use anyhow::{Context, anyhow};
use log::{debug, error, info, warn};
use seccompiler::{BpfProgram, SeccompAction, apply_filter};
use serde_json;
use thiserror::Error;
use vm_memory::bitmap::BitmapSlice;
@@ -30,6 +31,7 @@ use vm_migration::tls::{TlsServerConfig, TlsStream};
use vm_migration::{MigratableError, Snapshot};
use vmm_sys_util::eventfd::EventFd;
use crate::seccomp_filters::{Thread, get_seccomp_filter};
use crate::sync_utils::Gate;
use crate::{GuestMemoryMmap, VmMigrationConfig};
@@ -308,6 +310,7 @@ impl ReceiveAdditionalConnections {
listener: ReceiveListener,
guest_memory: GuestMemoryAtomic<GuestMemoryMmap>,
fault_tx: Sender<SocketStream>,
seccomp_action: &SeccompAction,
) -> Result<Self, MigratableError> {
let event_fd = EventFd::new(0)
.context("Error creating terminate fd")
@@ -318,10 +321,26 @@ impl ReceiveAdditionalConnections {
.context("Error cloning terminate fd")
.map_err(MigratableError::MigrateReceive)?;
let seccomp_filter = get_seccomp_filter(seccomp_action, Thread::MigrationTcpWorker, None)
.context("Error creating migration TCP worker seccomp filter")
.map_err(MigratableError::MigrateReceive)?;
let accept_thread = thread::Builder::new()
.name("migrate-receive-accept-connections".to_owned())
.spawn(move || {
Self::accept_connections(listener, &terminate_fd, &guest_memory, &fault_tx)
if !seccomp_filter.is_empty() {
apply_filter(&seccomp_filter)
.context("Error applying migration TCP worker seccomp filter")
.map_err(MigratableError::MigrateReceive)?;
}
Self::accept_connections(
listener,
&terminate_fd,
&guest_memory,
&fault_tx,
&seccomp_filter,
)
})
.context("Error creating connection accept thread")
.map_err(MigratableError::MigrateReceive)?;
@@ -348,6 +367,7 @@ impl ReceiveAdditionalConnections {
terminate_fd: &EventFd,
guest_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
fault_tx: &Sender<SocketStream>,
seccomp_filter: &BpfProgram,
) -> Result<(), MigratableError> {
let mut threads = Vec::new();
let first_err = Self::accept_connections_loop(
@@ -356,6 +376,7 @@ impl ReceiveAdditionalConnections {
guest_memory,
fault_tx,
&mut threads,
seccomp_filter,
);
if first_err.is_err() {
@@ -380,6 +401,7 @@ impl ReceiveAdditionalConnections {
guest_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
fault_tx: &Sender<SocketStream>,
threads: &mut Vec<thread::JoinHandle<Result<(), MigratableError>>>,
seccomp_filter: &BpfProgram,
) -> Result<(), MigratableError> {
loop {
let socket = listener.abortable_accept(terminate_fd)?;
@@ -402,6 +424,7 @@ impl ReceiveAdditionalConnections {
threads.len(),
terminate_fd,
guest_memory.clone(),
seccomp_filter,
)?;
threads.push(thread);
}
@@ -456,15 +479,24 @@ impl ReceiveAdditionalConnections {
index: usize,
terminate_fd: &EventFd,
guest_memory: GuestMemoryAtomic<GuestMemoryMmap>,
seccomp_filter: &BpfProgram,
) -> Result<thread::JoinHandle<Result<(), MigratableError>>, MigratableError> {
let terminate_fd = terminate_fd
.try_clone()
.context("Error cloning terminate fd")
.map_err(MigratableError::MigrateReceive)?;
let seccomp_filter_t = seccomp_filter.clone();
thread::Builder::new()
.name(format!("migrate-receive-memory-{index}"))
.spawn(move || Self::worker_receive_memory(&mut socket, &terminate_fd, &guest_memory))
.spawn(move || {
if !seccomp_filter_t.is_empty() {
apply_filter(&seccomp_filter_t)
.context("Error applying migration TCP worker seccomp filter")
.map_err(MigratableError::MigrateReceive)?;
}
Self::worker_receive_memory(&mut socket, &terminate_fd, &guest_memory)
})
.map_err(|e| {
error!("Error spawning receive-memory thread: {e}");
MigratableError::MigrateReceive(
@@ -652,6 +684,7 @@ impl SendAdditionalConnections {
connections: NonZeroU32,
tls_dir: Option<&Path>,
guest_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
seccomp_filter: &BpfProgram,
) -> Result<Self, MigratableError> {
let mut threads = Vec::new();
let configured_connections = connections.get();
@@ -683,10 +716,17 @@ impl SendAdditionalConnections {
let message_rx = message_rx.clone();
let worker_error = worker_error.clone();
let notify_tx = notify_tx.clone();
let seccomp_filter = seccomp_filter.clone();
let thread = thread::Builder::new()
.name(format!("migrate-send-memory-{n}"))
.spawn(move || {
if !seccomp_filter.is_empty() {
apply_filter(&seccomp_filter)
.context("Error applying migration TCP worker seccomp filter")
.map_err(MigratableError::MigrateReceive)?;
}
Self::worker_send_memory(
&mut socket,
&guest_memory,

View File

@@ -72,6 +72,7 @@ impl Drop for MigrationWorkerHandle {
#[derive(Clone, Debug)]
pub struct MigrationSeccompFilters {
pub worker: BpfProgram,
pub tcp_worker: BpfProgram,
pub postcopy_server: BpfProgram,
}

View File

@@ -39,7 +39,11 @@ pub enum Thread {
#[cfg(feature = "dbus_api")]
DBusApi,
EventMonitor,
/// Thread handling the migration on the sending side.
MigrationWorker,
/// Key used for the TCP workers for send and receive, as well as the accept
/// thread on the receiver side.
MigrationTcpWorker,
SignalHandler,
Vcpu,
Vmm,
@@ -1124,6 +1128,52 @@ fn migration_thread_rules() -> Result<Vec<(i64, Vec<SeccompRule>)>, BackendError
])
}
fn migration_tcp_worker_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_clone, vec![]),
(libc::SYS_clone3, vec![]),
(libc::SYS_close, vec![]),
(libc::SYS_exit, vec![]),
(libc::SYS_exit_group, vec![]),
(libc::SYS_fcntl, 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_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_pwrite64, vec![]),
(libc::SYS_read, vec![]),
(libc::SYS_readv, 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![]),
// We are already inheriting seccomp from the parent thread.
(libc::SYS_seccomp, vec![]),
(libc::SYS_sendmsg, vec![]),
(libc::SYS_sendto, vec![]),
(libc::SYS_set_robust_list, vec![]),
(libc::SYS_setsockopt, vec![]),
(libc::SYS_sigaltstack, 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![]),
@@ -1193,6 +1243,7 @@ fn get_seccomp_rules(
Thread::DBusApi => dbus_api_thread_rules()?,
Thread::EventMonitor => event_monitor_thread_rules()?,
Thread::MigrationWorker => migration_thread_rules()?,
Thread::MigrationTcpWorker => migration_tcp_worker_thread_rules()?,
Thread::SerialManager => serial_manager_thread_rules()?,
Thread::SignalHandler => signal_handler_thread_rules()?,
Thread::Vcpu => vcpu_thread_rules(