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 log::{debug, error, info, trace, warn};
|
||||||
use memory_manager::MemoryManagerSnapshotData;
|
use memory_manager::MemoryManagerSnapshotData;
|
||||||
use pci::PciBdf;
|
use pci::PciBdf;
|
||||||
use seccompiler::{SeccompAction, apply_filter};
|
use seccompiler::{BpfProgram, SeccompAction, apply_filter};
|
||||||
use serde::ser::{SerializeStruct, Serializer};
|
use serde::ser::{SerializeStruct, Serializer};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use signal_hook::iterator::{Handle, Signals};
|
use signal_hook::iterator::{Handle, Signals};
|
||||||
@@ -1531,6 +1531,7 @@ impl Vmm {
|
|||||||
hypervisor: &dyn hypervisor::Hypervisor,
|
hypervisor: &dyn hypervisor::Hypervisor,
|
||||||
send_data_migration: &VmSendMigrationData,
|
send_data_migration: &VmSendMigrationData,
|
||||||
initial_vm_state: VmState,
|
initial_vm_state: VmState,
|
||||||
|
seccomp_action: &SeccompAction,
|
||||||
) -> result::Result<(), MigratableError> {
|
) -> result::Result<(), MigratableError> {
|
||||||
// State machine that is updated with more context as we progress.
|
// State machine that is updated with more context as we progress.
|
||||||
let mut ctx = OngoingMigrationContext::new();
|
let mut ctx = OngoingMigrationContext::new();
|
||||||
@@ -1667,9 +1668,19 @@ impl Vmm {
|
|||||||
send_data_migration.tls_dir.as_deref(),
|
send_data_migration.tls_dir.as_deref(),
|
||||||
)?;
|
)?;
|
||||||
let guest_memory = vm.guest_memory();
|
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()
|
let handle = thread::Builder::new()
|
||||||
.name("migrate-send-postcopy".to_owned())
|
.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| {
|
.map_err(|e| {
|
||||||
MigratableError::MigrateSend(anyhow!("spawning postcopy serve thread: {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"
|
reason = "runs on a dedicated thread and must own its arguments"
|
||||||
)]
|
)]
|
||||||
fn serve_postcopy(
|
fn serve_postcopy(
|
||||||
|
seccomp_filter: BpfProgram,
|
||||||
mut socket: SocketStream,
|
mut socket: SocketStream,
|
||||||
guest_memory: GuestMemoryAtomic<GuestMemoryMmap>,
|
guest_memory: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||||
) -> result::Result<(), MigratableError> {
|
) -> 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();
|
let mut buf: Vec<u8> = Vec::new();
|
||||||
info!("Postcopy: source entering PageFault serve loop");
|
info!("Postcopy: source entering PageFault serve loop");
|
||||||
|
|
||||||
@@ -3099,6 +3120,7 @@ impl RequestHandler for Vmm {
|
|||||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||||
self.hypervisor.clone(),
|
self.hypervisor.clone(),
|
||||||
initial_vm_state,
|
initial_vm_state,
|
||||||
|
self.seccomp_action.clone(),
|
||||||
) {
|
) {
|
||||||
Ok(handle) => {
|
Ok(handle) => {
|
||||||
self.vm = VmOwnership::Migration {
|
self.vm = VmOwnership::Migration {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ use std::thread::JoinHandle;
|
|||||||
|
|
||||||
use event_monitor::event;
|
use event_monitor::event;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
|
use seccompiler::SeccompAction;
|
||||||
use vm_migration::MigratableError;
|
use vm_migration::MigratableError;
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
@@ -75,6 +76,7 @@ pub struct MigrationWorker {
|
|||||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||||
hypervisor: Arc<dyn hypervisor::Hypervisor>,
|
hypervisor: Arc<dyn hypervisor::Hypervisor>,
|
||||||
initial_vm_state: VmState,
|
initial_vm_state: VmState,
|
||||||
|
seccomp_action: SeccompAction,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MigrationWorker {
|
impl MigrationWorker {
|
||||||
@@ -90,6 +92,7 @@ impl MigrationWorker {
|
|||||||
self.hypervisor.as_ref(),
|
self.hypervisor.as_ref(),
|
||||||
&self.config,
|
&self.config,
|
||||||
self.initial_vm_state,
|
self.initial_vm_state,
|
||||||
|
&self.seccomp_action,
|
||||||
)
|
)
|
||||||
.inspect(|_| event!("vm", "migration-finished"))
|
.inspect(|_| event!("vm", "migration-finished"))
|
||||||
.inspect_err(|_| event!("vm", "migration-failed"));
|
.inspect_err(|_| event!("vm", "migration-failed"));
|
||||||
@@ -116,6 +119,7 @@ impl MigrationWorker {
|
|||||||
dyn hypervisor::Hypervisor,
|
dyn hypervisor::Hypervisor,
|
||||||
>,
|
>,
|
||||||
initial_vm_state: VmState,
|
initial_vm_state: VmState,
|
||||||
|
seccomp_action: SeccompAction,
|
||||||
) -> Result<MigrationWorkerHandle, MigrationWorkerSpawnError> {
|
) -> Result<MigrationWorkerHandle, MigrationWorkerSpawnError> {
|
||||||
let (vm_sender, vm_receiver) = std::sync::mpsc::sync_channel(0);
|
let (vm_sender, vm_receiver) = std::sync::mpsc::sync_channel(0);
|
||||||
let worker = MigrationWorker {
|
let worker = MigrationWorker {
|
||||||
@@ -125,6 +129,7 @@ impl MigrationWorker {
|
|||||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||||
hypervisor,
|
hypervisor,
|
||||||
initial_vm_state,
|
initial_vm_state,
|
||||||
|
seccomp_action,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inner_handle = match thread::Builder::new()
|
let inner_handle = match thread::Builder::new()
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ pub enum Thread {
|
|||||||
Vmm,
|
Vmm,
|
||||||
PtyForeground,
|
PtyForeground,
|
||||||
SerialManager,
|
SerialManager,
|
||||||
|
MigrateSendPostcopy,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shorthand for chaining `SeccompCondition`s with the `and` operator in a `SeccompRule`.
|
/// 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(
|
fn get_seccomp_rules(
|
||||||
thread_type: Thread,
|
thread_type: Thread,
|
||||||
hypervisor_type: Option<HypervisorType>,
|
hypervisor_type: Option<HypervisorType>,
|
||||||
@@ -1102,6 +1132,7 @@ fn get_seccomp_rules(
|
|||||||
hypervisor_type.expect("hypervisor_type is required for Vmm threads"),
|
hypervisor_type.expect("hypervisor_type is required for Vmm threads"),
|
||||||
)?),
|
)?),
|
||||||
Thread::PtyForeground => Ok(pty_foreground_thread_rules()?),
|
Thread::PtyForeground => Ok(pty_foreground_thread_rules()?),
|
||||||
|
Thread::MigrateSendPostcopy => Ok(migrate_send_postcopy_thread_rules()?),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user