mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
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:
committed by
Bo Chen
parent
fd88e23ecb
commit
1ae1cc787d
+18
-1
@@ -980,7 +980,12 @@ impl Vmm {
|
|||||||
// The accept thread hands the page fault connection back via this channel.
|
// The accept thread hands the page fault connection back via this channel.
|
||||||
let (fault_tx, fault_rx) = channel();
|
let (fault_tx, fault_rx) = channel();
|
||||||
let connections = listener.try_clone().and_then(|l| {
|
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 {
|
Ok(ReceiveMigrationConfiguredData {
|
||||||
memory_manager,
|
memory_manager,
|
||||||
@@ -1652,6 +1657,7 @@ impl Vmm {
|
|||||||
send_data_migration.connections,
|
send_data_migration.connections,
|
||||||
send_data_migration.tls_dir.as_deref(),
|
send_data_migration.tls_dir.as_deref(),
|
||||||
&vm.guest_memory(),
|
&vm.guest_memory(),
|
||||||
|
&seccomp_filters.tcp_worker,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Self::do_memory_migration(
|
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 =
|
let postcopy_server =
|
||||||
get_seccomp_filter(&self.seccomp_action, Thread::MigrateSendPostcopy, None)
|
get_seccomp_filter(&self.seccomp_action, Thread::MigrateSendPostcopy, None)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
@@ -3169,6 +3185,7 @@ impl RequestHandler for Vmm {
|
|||||||
|
|
||||||
MigrationSeccompFilters {
|
MigrationSeccompFilters {
|
||||||
worker,
|
worker,
|
||||||
|
tcp_worker,
|
||||||
postcopy_server,
|
postcopy_server,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ use std::{mem, thread};
|
|||||||
|
|
||||||
use anyhow::{Context, anyhow};
|
use anyhow::{Context, anyhow};
|
||||||
use log::{debug, error, info, warn};
|
use log::{debug, error, info, warn};
|
||||||
|
use seccompiler::{BpfProgram, SeccompAction, apply_filter};
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use vm_memory::bitmap::BitmapSlice;
|
use vm_memory::bitmap::BitmapSlice;
|
||||||
@@ -30,6 +31,7 @@ use vm_migration::tls::{TlsServerConfig, TlsStream};
|
|||||||
use vm_migration::{MigratableError, Snapshot};
|
use vm_migration::{MigratableError, Snapshot};
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
|
use crate::seccomp_filters::{Thread, get_seccomp_filter};
|
||||||
use crate::sync_utils::Gate;
|
use crate::sync_utils::Gate;
|
||||||
use crate::{GuestMemoryMmap, VmMigrationConfig};
|
use crate::{GuestMemoryMmap, VmMigrationConfig};
|
||||||
|
|
||||||
@@ -308,6 +310,7 @@ impl ReceiveAdditionalConnections {
|
|||||||
listener: ReceiveListener,
|
listener: ReceiveListener,
|
||||||
guest_memory: GuestMemoryAtomic<GuestMemoryMmap>,
|
guest_memory: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||||
fault_tx: Sender<SocketStream>,
|
fault_tx: Sender<SocketStream>,
|
||||||
|
seccomp_action: &SeccompAction,
|
||||||
) -> Result<Self, MigratableError> {
|
) -> Result<Self, MigratableError> {
|
||||||
let event_fd = EventFd::new(0)
|
let event_fd = EventFd::new(0)
|
||||||
.context("Error creating terminate fd")
|
.context("Error creating terminate fd")
|
||||||
@@ -318,10 +321,26 @@ impl ReceiveAdditionalConnections {
|
|||||||
.context("Error cloning terminate fd")
|
.context("Error cloning terminate fd")
|
||||||
.map_err(MigratableError::MigrateReceive)?;
|
.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()
|
let accept_thread = thread::Builder::new()
|
||||||
.name("migrate-receive-accept-connections".to_owned())
|
.name("migrate-receive-accept-connections".to_owned())
|
||||||
.spawn(move || {
|
.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")
|
.context("Error creating connection accept thread")
|
||||||
.map_err(MigratableError::MigrateReceive)?;
|
.map_err(MigratableError::MigrateReceive)?;
|
||||||
@@ -348,6 +367,7 @@ impl ReceiveAdditionalConnections {
|
|||||||
terminate_fd: &EventFd,
|
terminate_fd: &EventFd,
|
||||||
guest_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
|
guest_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
|
||||||
fault_tx: &Sender<SocketStream>,
|
fault_tx: &Sender<SocketStream>,
|
||||||
|
seccomp_filter: &BpfProgram,
|
||||||
) -> Result<(), MigratableError> {
|
) -> Result<(), MigratableError> {
|
||||||
let mut threads = Vec::new();
|
let mut threads = Vec::new();
|
||||||
let first_err = Self::accept_connections_loop(
|
let first_err = Self::accept_connections_loop(
|
||||||
@@ -356,6 +376,7 @@ impl ReceiveAdditionalConnections {
|
|||||||
guest_memory,
|
guest_memory,
|
||||||
fault_tx,
|
fault_tx,
|
||||||
&mut threads,
|
&mut threads,
|
||||||
|
seccomp_filter,
|
||||||
);
|
);
|
||||||
|
|
||||||
if first_err.is_err() {
|
if first_err.is_err() {
|
||||||
@@ -380,6 +401,7 @@ impl ReceiveAdditionalConnections {
|
|||||||
guest_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
|
guest_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
|
||||||
fault_tx: &Sender<SocketStream>,
|
fault_tx: &Sender<SocketStream>,
|
||||||
threads: &mut Vec<thread::JoinHandle<Result<(), MigratableError>>>,
|
threads: &mut Vec<thread::JoinHandle<Result<(), MigratableError>>>,
|
||||||
|
seccomp_filter: &BpfProgram,
|
||||||
) -> Result<(), MigratableError> {
|
) -> Result<(), MigratableError> {
|
||||||
loop {
|
loop {
|
||||||
let socket = listener.abortable_accept(terminate_fd)?;
|
let socket = listener.abortable_accept(terminate_fd)?;
|
||||||
@@ -402,6 +424,7 @@ impl ReceiveAdditionalConnections {
|
|||||||
threads.len(),
|
threads.len(),
|
||||||
terminate_fd,
|
terminate_fd,
|
||||||
guest_memory.clone(),
|
guest_memory.clone(),
|
||||||
|
seccomp_filter,
|
||||||
)?;
|
)?;
|
||||||
threads.push(thread);
|
threads.push(thread);
|
||||||
}
|
}
|
||||||
@@ -456,15 +479,24 @@ impl ReceiveAdditionalConnections {
|
|||||||
index: usize,
|
index: usize,
|
||||||
terminate_fd: &EventFd,
|
terminate_fd: &EventFd,
|
||||||
guest_memory: GuestMemoryAtomic<GuestMemoryMmap>,
|
guest_memory: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||||
|
seccomp_filter: &BpfProgram,
|
||||||
) -> Result<thread::JoinHandle<Result<(), MigratableError>>, MigratableError> {
|
) -> Result<thread::JoinHandle<Result<(), MigratableError>>, MigratableError> {
|
||||||
let terminate_fd = terminate_fd
|
let terminate_fd = terminate_fd
|
||||||
.try_clone()
|
.try_clone()
|
||||||
.context("Error cloning terminate fd")
|
.context("Error cloning terminate fd")
|
||||||
.map_err(MigratableError::MigrateReceive)?;
|
.map_err(MigratableError::MigrateReceive)?;
|
||||||
|
|
||||||
|
let seccomp_filter_t = seccomp_filter.clone();
|
||||||
thread::Builder::new()
|
thread::Builder::new()
|
||||||
.name(format!("migrate-receive-memory-{index}"))
|
.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| {
|
.map_err(|e| {
|
||||||
error!("Error spawning receive-memory thread: {e}");
|
error!("Error spawning receive-memory thread: {e}");
|
||||||
MigratableError::MigrateReceive(
|
MigratableError::MigrateReceive(
|
||||||
@@ -652,6 +684,7 @@ impl SendAdditionalConnections {
|
|||||||
connections: NonZeroU32,
|
connections: NonZeroU32,
|
||||||
tls_dir: Option<&Path>,
|
tls_dir: Option<&Path>,
|
||||||
guest_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
|
guest_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
|
||||||
|
seccomp_filter: &BpfProgram,
|
||||||
) -> Result<Self, MigratableError> {
|
) -> Result<Self, MigratableError> {
|
||||||
let mut threads = Vec::new();
|
let mut threads = Vec::new();
|
||||||
let configured_connections = connections.get();
|
let configured_connections = connections.get();
|
||||||
@@ -683,10 +716,17 @@ impl SendAdditionalConnections {
|
|||||||
let message_rx = message_rx.clone();
|
let message_rx = message_rx.clone();
|
||||||
let worker_error = worker_error.clone();
|
let worker_error = worker_error.clone();
|
||||||
let notify_tx = notify_tx.clone();
|
let notify_tx = notify_tx.clone();
|
||||||
|
let seccomp_filter = seccomp_filter.clone();
|
||||||
|
|
||||||
let thread = thread::Builder::new()
|
let thread = thread::Builder::new()
|
||||||
.name(format!("migrate-send-memory-{n}"))
|
.name(format!("migrate-send-memory-{n}"))
|
||||||
.spawn(move || {
|
.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(
|
Self::worker_send_memory(
|
||||||
&mut socket,
|
&mut socket,
|
||||||
&guest_memory,
|
&guest_memory,
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ impl Drop for MigrationWorkerHandle {
|
|||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct MigrationSeccompFilters {
|
pub struct MigrationSeccompFilters {
|
||||||
pub worker: BpfProgram,
|
pub worker: BpfProgram,
|
||||||
|
pub tcp_worker: BpfProgram,
|
||||||
pub postcopy_server: BpfProgram,
|
pub postcopy_server: BpfProgram,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,11 @@ pub enum Thread {
|
|||||||
#[cfg(feature = "dbus_api")]
|
#[cfg(feature = "dbus_api")]
|
||||||
DBusApi,
|
DBusApi,
|
||||||
EventMonitor,
|
EventMonitor,
|
||||||
|
/// Thread handling the migration on the sending side.
|
||||||
MigrationWorker,
|
MigrationWorker,
|
||||||
|
/// Key used for the TCP workers for send and receive, as well as the accept
|
||||||
|
/// thread on the receiver side.
|
||||||
|
MigrationTcpWorker,
|
||||||
SignalHandler,
|
SignalHandler,
|
||||||
Vcpu,
|
Vcpu,
|
||||||
Vmm,
|
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> {
|
fn serial_manager_thread_rules() -> Result<Vec<(i64, Vec<SeccompRule>)>, BackendError> {
|
||||||
Ok(vec![
|
Ok(vec![
|
||||||
(libc::SYS_accept4, vec![]),
|
(libc::SYS_accept4, vec![]),
|
||||||
@@ -1193,6 +1243,7 @@ fn get_seccomp_rules(
|
|||||||
Thread::DBusApi => dbus_api_thread_rules()?,
|
Thread::DBusApi => dbus_api_thread_rules()?,
|
||||||
Thread::EventMonitor => event_monitor_thread_rules()?,
|
Thread::EventMonitor => event_monitor_thread_rules()?,
|
||||||
Thread::MigrationWorker => migration_thread_rules()?,
|
Thread::MigrationWorker => migration_thread_rules()?,
|
||||||
|
Thread::MigrationTcpWorker => migration_tcp_worker_thread_rules()?,
|
||||||
Thread::SerialManager => serial_manager_thread_rules()?,
|
Thread::SerialManager => serial_manager_thread_rules()?,
|
||||||
Thread::SignalHandler => signal_handler_thread_rules()?,
|
Thread::SignalHandler => signal_handler_thread_rules()?,
|
||||||
Thread::Vcpu => vcpu_thread_rules(
|
Thread::Vcpu => vcpu_thread_rules(
|
||||||
|
|||||||
Reference in New Issue
Block a user