diff --git a/arch/src/aarch64/mod.rs b/arch/src/aarch64/mod.rs index afc051489..124b8cbe9 100644 --- a/arch/src/aarch64/mod.rs +++ b/arch/src/aarch64/mod.rs @@ -21,6 +21,8 @@ use std::fmt::Debug; use std::sync::{Arc, Mutex}; use vm_memory::{Address, GuestAddress, GuestMemory, GuestMemoryAtomic, GuestUsize}; +pub const _NSIG: i32 = 65; + /// Errors thrown while configuring aarch64 system. #[derive(Debug)] pub enum Error { diff --git a/arch/src/lib.rs b/arch/src/lib.rs index dc1f90d95..62cd1df6c 100644 --- a/arch/src/lib.rs +++ b/arch/src/lib.rs @@ -82,7 +82,7 @@ pub mod aarch64; pub use aarch64::{ arch_memory_regions, configure_system, configure_vcpu, fdt::DeviceInfoForFdt, get_host_cpu_phys_bits, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE, - layout::IRQ_BASE, uefi, EntryPoint, + layout::IRQ_BASE, uefi, EntryPoint, _NSIG, }; #[cfg(target_arch = "x86_64")] @@ -92,7 +92,7 @@ pub mod x86_64; pub use x86_64::{ arch_memory_regions, configure_system, configure_vcpu, generate_common_cpuid, get_host_cpu_phys_bits, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE, - layout::CMDLINE_START, regs, CpuidFeatureEntry, EntryPoint, + layout::CMDLINE_START, regs, CpuidFeatureEntry, EntryPoint, _NSIG, }; /// Safe wrapper for `sysconf(_SC_PAGESIZE)`. diff --git a/arch/src/x86_64/mod.rs b/arch/src/x86_64/mod.rs index aacacd06e..3bdc01ee7 100644 --- a/arch/src/x86_64/mod.rs +++ b/arch/src/x86_64/mod.rs @@ -53,6 +53,8 @@ const KVM_FEATURE_ASYNC_PF_VMEXIT_BIT: u8 = 10; #[cfg(feature = "tdx")] const KVM_FEATURE_STEAL_TIME_BIT: u8 = 5; +pub const _NSIG: i32 = 65; + #[derive(Debug, Copy, Clone)] /// Specifies the entry point address where the guest must start /// executing code, as well as which of the supported boot protocols diff --git a/vmm/src/sigwinch_listener.rs b/vmm/src/sigwinch_listener.rs index d789bc445..cad87f883 100644 --- a/vmm/src/sigwinch_listener.rs +++ b/vmm/src/sigwinch_listener.rs @@ -2,10 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 use crate::clone3::{clone3, clone_args, CLONE_CLEAR_SIGHAND}; +use arch::_NSIG; use libc::{ - c_int, c_void, close, getpgrp, ioctl, pipe2, poll, pollfd, setsid, sigemptyset, siginfo_t, - sigprocmask, syscall, tcsetpgrp, SYS_close_range, ENOSYS, O_CLOEXEC, POLLERR, SIGWINCH, - SIG_SETMASK, STDERR_FILENO, TIOCSCTTY, + c_int, c_void, close, fork, getpgrp, ioctl, pipe2, poll, pollfd, setsid, sigemptyset, + siginfo_t, signal, sigprocmask, syscall, tcsetpgrp, SYS_close_range, EINVAL, ENOSYS, O_CLOEXEC, + POLLERR, SIGWINCH, SIG_DFL, SIG_SETMASK, STDERR_FILENO, TIOCSCTTY, }; use seccompiler::{apply_filter, BpfProgram}; use std::cell::RefCell; @@ -176,6 +177,35 @@ fn sigwinch_listener_main(seccomp_filter: BpfProgram, tx: File, pty: File) -> ! exit(0); } +/// # Safety +/// +/// Same as [`fork`]. +unsafe fn clone_clear_sighand() -> io::Result { + let mut args = clone_args::default(); + args.flags |= CLONE_CLEAR_SIGHAND; + let r = clone3(&mut args, size_of::()); + if r != -1 { + return Ok(r.try_into().unwrap()); + } + let e = io::Error::last_os_error(); + if e.raw_os_error() != Some(ENOSYS) && e.raw_os_error() != Some(EINVAL) { + return Err(e); + } + + // If CLONE_CLEAR_SIGHAND isn't available, fall back to resetting + // all the signal handlers one by one. + let r = fork(); + if r == -1 { + return Err(io::Error::last_os_error()); + } + if r == 0 { + for signum in 1.._NSIG { + let _ = signal(signum, SIG_DFL); + } + } + Ok(r.try_into().unwrap()) +} + pub fn start_sigwinch_listener(seccomp_filter: BpfProgram, tty_sub: File) -> io::Result { let mut pipe = [-1; 2]; // SAFETY: FFI call with valid arguments @@ -188,16 +218,9 @@ pub fn start_sigwinch_listener(seccomp_filter: BpfProgram, tty_sub: File) -> io: // SAFETY: pipe[1] is valid let tx = unsafe { File::from_raw_fd(pipe[1]) }; - let mut args = clone_args::default(); - args.flags |= CLONE_CLEAR_SIGHAND; - // SAFETY: FFI call - match unsafe { clone3(&mut args, size_of::()) } { - -1 => return Err(io::Error::last_os_error()), - 0 => { - sigwinch_listener_main(seccomp_filter, tx, tty_sub); - } - _ => (), + if unsafe { clone_clear_sighand() }? == 0 { + sigwinch_listener_main(seccomp_filter, tx, tty_sub); } drop(tx);