mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vmm: add seccomp filter for serial-manager thread
The serial-manager thread was the only VMM-managed thread without a seccomp filter. Add a Thread::SerialManager variant and whitelist the 31 syscalls needed for its epoll-based I/O loop (read, write, socket ops, signal handling, memory allocation, glibc internals). The filter is computed in start_thread() and applied before the epoll loop, matching the pattern used by other VMM threads. Signed-off-by: Wei Liu <liuwe@microsoft.com> Assisted-by: Pi-agent:Claude-Opus-4.7
This commit is contained in:
@@ -2534,6 +2534,7 @@ impl DeviceManager {
|
||||
self.exit_evt
|
||||
.try_clone()
|
||||
.map_err(DeviceManagerError::EventFd)?,
|
||||
&self.seccomp_action,
|
||||
)
|
||||
.map_err(DeviceManagerError::SpawnSerialManager)?;
|
||||
Some(Arc::new(serial_manager))
|
||||
|
||||
@@ -39,6 +39,7 @@ pub enum Thread {
|
||||
Vcpu,
|
||||
Vmm,
|
||||
PtyForeground,
|
||||
SerialManager,
|
||||
}
|
||||
|
||||
/// Shorthand for chaining `SeccompCondition`s with the `and` operator in a `SeccompRule`.
|
||||
@@ -1031,6 +1032,33 @@ fn event_monitor_thread_rules() -> Result<Vec<(i64, Vec<SeccompRule>)>, BackendE
|
||||
])
|
||||
}
|
||||
|
||||
fn serial_manager_thread_rules() -> Result<Vec<(i64, Vec<SeccompRule>)>, BackendError> {
|
||||
Ok(vec![
|
||||
(libc::SYS_accept4, vec![]),
|
||||
(libc::SYS_clock_nanosleep, vec![]),
|
||||
(libc::SYS_clock_gettime, vec![]),
|
||||
(libc::SYS_close, vec![]),
|
||||
(libc::SYS_epoll_ctl, vec![]),
|
||||
(libc::SYS_epoll_pwait, vec![]),
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
(libc::SYS_epoll_wait, vec![]),
|
||||
(libc::SYS_exit, vec![]),
|
||||
(libc::SYS_fcntl, vec![]),
|
||||
(libc::SYS_futex, vec![]),
|
||||
(libc::SYS_madvise, vec![]),
|
||||
(libc::SYS_mmap, vec![]),
|
||||
(libc::SYS_munmap, vec![]),
|
||||
(libc::SYS_nanosleep, vec![]),
|
||||
(libc::SYS_read, vec![]),
|
||||
(libc::SYS_recvfrom, vec![]),
|
||||
(libc::SYS_rt_sigprocmask, vec![]),
|
||||
(libc::SYS_rt_sigreturn, vec![]),
|
||||
(libc::SYS_shutdown, vec![]),
|
||||
(libc::SYS_sigaltstack, vec![]),
|
||||
(libc::SYS_write, vec![]),
|
||||
])
|
||||
}
|
||||
|
||||
fn get_seccomp_rules(
|
||||
thread_type: Thread,
|
||||
hypervisor_type: Option<HypervisorType>,
|
||||
@@ -1040,6 +1068,7 @@ fn get_seccomp_rules(
|
||||
#[cfg(feature = "dbus_api")]
|
||||
Thread::DBusApi => Ok(dbus_api_thread_rules()?),
|
||||
Thread::EventMonitor => Ok(event_monitor_thread_rules()?),
|
||||
Thread::SerialManager => Ok(serial_manager_thread_rules()?),
|
||||
Thread::SignalHandler => Ok(signal_handler_thread_rules()?),
|
||||
Thread::Vcpu => Ok(vcpu_thread_rules(
|
||||
hypervisor_type.expect("hypervisor_type is required for Vcpu threads"),
|
||||
|
||||
@@ -21,11 +21,13 @@ use devices::legacy::Pl011;
|
||||
use devices::legacy::Serial;
|
||||
use libc::EFD_NONBLOCK;
|
||||
use log::{error, info, warn};
|
||||
use seccompiler::{SeccompAction, apply_filter};
|
||||
use serial_buffer::SerialBuffer;
|
||||
use thiserror::Error;
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
use crate::console_devices::ConsoleTransport;
|
||||
use crate::seccomp_filters::{Thread, get_seccomp_filter};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum Error {
|
||||
@@ -84,6 +86,14 @@ pub enum Error {
|
||||
/// Cannot duplicate file descriptor
|
||||
#[error("Error duplicating file descriptor")]
|
||||
DupFd(#[source] io::Error),
|
||||
|
||||
/// Cannot create seccomp filter.
|
||||
#[error("Error creating seccomp filter")]
|
||||
CreateSeccompFilter(seccompiler::Error),
|
||||
|
||||
/// Cannot apply seccomp filter.
|
||||
#[error("Error applying seccomp filter")]
|
||||
ApplySeccompFilter(seccompiler::Error),
|
||||
}
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
@@ -250,13 +260,20 @@ impl SerialManager {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn start_thread(&mut self, exit_evt: EventFd) -> Result<()> {
|
||||
pub fn start_thread(
|
||||
&mut self,
|
||||
exit_evt: EventFd,
|
||||
seccomp_action: &SeccompAction,
|
||||
) -> Result<()> {
|
||||
// Don't allow this to be run if the handle exists
|
||||
if self.handle.is_some() {
|
||||
warn!("Tried to start multiple SerialManager threads, ignoring");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let seccomp_filter = get_seccomp_filter(seccomp_action, Thread::SerialManager, None)
|
||||
.map_err(Error::CreateSeccompFilter)?;
|
||||
|
||||
let epoll_fd = self.epoll_fd.try_clone().map_err(Error::Epoll)?;
|
||||
let transport = self.transport.clone();
|
||||
let serial = self.serial.clone();
|
||||
@@ -275,6 +292,11 @@ impl SerialManager {
|
||||
.name("serial-manager".to_string())
|
||||
.spawn(move || {
|
||||
std::panic::catch_unwind(AssertUnwindSafe(move || {
|
||||
// Apply seccomp filter for serial manager thread.
|
||||
if !seccomp_filter.is_empty() {
|
||||
apply_filter(&seccomp_filter).map_err(Error::ApplySeccompFilter)?;
|
||||
}
|
||||
|
||||
let mut events =
|
||||
[epoll::Event::new(epoll::Events::empty(), 0); EPOLL_EVENTS_LEN];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user