diff --git a/src/libos/src/net/syscalls.rs b/src/libos/src/net/syscalls.rs index dc962433..d78cef66 100644 --- a/src/libos/src/net/syscalls.rs +++ b/src/libos/src/net/syscalls.rs @@ -7,7 +7,7 @@ use super::io_multiplexing::{AsEpollFile, EpollCtl, EpollFile, EpollFlags, FdSet use fs::{CreationFlags, File, FileDesc, FileRef}; use misc::resource_t; use process::Process; -use signal::{sigset_t, SigSet}; +use signal::{do_sigprocmask, sigset_t, MaskOp, SigSet}; use std::convert::TryFrom; use time::{timespec_t, timeval_t}; use util::mem_util::from_user; @@ -723,6 +723,109 @@ pub fn do_select( ret } +#[derive(Clone, Copy, Debug)] +#[repr(C)] +pub struct Pselect6sig { + ss: *const sigset_t, + ss_len: size_t, +} + +pub fn do_pselect6( + nfds: c_int, + readfds: *mut libc::fd_set, + writefds: *mut libc::fd_set, + exceptfds: *mut libc::fd_set, + timeout: *mut timespec_t, + sig_data: *const Pselect6sig, +) -> Result { + let mut is_set_sig = false; + let mut original_sig_set = sigset_t::default(); + + if !sig_data.is_null() { + from_user::check_ptr(sig_data)?; + let user_sig_data = unsafe { &*(sig_data) }; + + is_set_sig = !user_sig_data.ss.is_null(); + if is_set_sig { + if user_sig_data.ss_len != std::mem::size_of::() { + return_errno!(EINVAL, "unexpected sigset size"); + } + let op_and_set = { + let op = MaskOp::SetMask; + let sigset = user_sig_data.ss; + from_user::check_ptr(sigset)?; + let set = unsafe { &*sigset }; + Some((op, set)) + }; + + do_sigprocmask::do_rt_sigprocmask(op_and_set, Some(&mut original_sig_set))?; + } + } + + let nfds = { + let soft_rlimit_nofile = current!() + .rlimits() + .lock() + .unwrap() + .get(resource_t::RLIMIT_NOFILE) + .get_cur(); + if nfds < 0 || nfds > libc::FD_SETSIZE as i32 || nfds as u64 > soft_rlimit_nofile { + return_errno!( + EINVAL, + "nfds is negative or exceeds the resource limit or FD_SETSIZE" + ); + } + nfds as FileDesc + }; + + let mut timeout_c = if !timeout.is_null() { + from_user::check_ptr(timeout)?; + let timeval = unsafe { &mut *timeout }; + timeval.validate()?; + Some(timeval) + } else { + None + }; + let mut timeout = timeout_c.as_ref().map(|timeout_c| timeout_c.as_duration()); + + let readfds = if !readfds.is_null() { + from_user::check_mut_ptr(readfds)?; + Some(unsafe { &mut *readfds }) + } else { + None + }; + let writefds = if !writefds.is_null() { + from_user::check_mut_ptr(writefds)?; + Some(unsafe { &mut *writefds }) + } else { + None + }; + let exceptfds = if !exceptfds.is_null() { + from_user::check_mut_ptr(exceptfds)?; + Some(unsafe { &mut *exceptfds }) + } else { + None + }; + + let ret = io_multiplexing::do_select(nfds, readfds, writefds, exceptfds, timeout.as_mut()); + + if let Some(timeout_c) = timeout_c { + *timeout_c = timeout.unwrap().into(); + } + + // Restore the original signal mask + if is_set_sig { + let op_and_set = { + let op = MaskOp::SetMask; + let set = &original_sig_set; + Some((op, set)) + }; + do_sigprocmask::do_rt_sigprocmask(op_and_set, None)?; + } + + ret +} + pub fn do_ppoll( fds: *mut libc::pollfd, nfds: libc::nfds_t, diff --git a/src/libos/src/signal/mod.rs b/src/libos/src/signal/mod.rs index 8e8b7db1..c2cbe448 100644 --- a/src/libos/src/signal/mod.rs +++ b/src/libos/src/signal/mod.rs @@ -7,6 +7,7 @@ use sig_action::{SigAction, SigActionFlags, SigDefaultAction}; pub use self::c_types::{sigaction_t, siginfo_t, sigset_t, stack_t}; pub use self::constants::*; pub use self::do_kill::do_kill_from_outside_enclave; +pub use self::do_sigprocmask::MaskOp; pub use self::do_sigreturn::{deliver_signal, force_signal}; pub use self::sig_dispositions::SigDispositions; pub use self::sig_num::SigNum; @@ -21,7 +22,6 @@ mod do_kill; mod do_sigaction; mod do_sigaltstack; mod do_sigpending; -mod do_sigprocmask; mod do_sigreturn; mod do_sigtimedwait; mod sig_action; @@ -34,3 +34,4 @@ mod signals; mod syscalls; pub mod constants; +pub mod do_sigprocmask; diff --git a/src/libos/src/syscall/mod.rs b/src/libos/src/syscall/mod.rs index 2febe775..32190de8 100644 --- a/src/libos/src/syscall/mod.rs +++ b/src/libos/src/syscall/mod.rs @@ -43,8 +43,9 @@ use crate::misc::{resource_t, rlimit_t, sysinfo_t, utsname_t, RandFlags}; use crate::net::{ do_accept, do_accept4, do_bind, do_connect, do_epoll_create, do_epoll_create1, do_epoll_ctl, do_epoll_pwait, do_epoll_wait, do_getpeername, do_getsockname, do_getsockopt, do_listen, - do_poll, do_ppoll, do_recvfrom, do_recvmsg, do_select, do_sendmmsg, do_sendmsg, do_sendto, - do_setsockopt, do_shutdown, do_socket, do_socketpair, mmsghdr, msghdr, msghdr_mut, + do_poll, do_ppoll, do_pselect6, do_recvfrom, do_recvmsg, do_select, do_sendmmsg, do_sendmsg, + do_sendto, do_setsockopt, do_shutdown, do_socket, do_socketpair, mmsghdr, msghdr, msghdr_mut, + Pselect6sig, }; use crate::process::{ do_arch_prctl, do_clone, do_execve, do_exit, do_exit_group, do_futex, do_get_robust_list, @@ -366,7 +367,7 @@ macro_rules! process_syscall_table_with_callback { (Readlinkat = 267) => do_readlinkat(dirfd: i32, path: *const i8, buf: *mut u8, size: usize), (Fchmodat = 268) => do_fchmodat(dirfd: i32, path: *const i8, mode: u16), (Faccessat = 269) => do_faccessat(dirfd: i32, path: *const i8, mode: u32, flags: u32), - (Pselect6 = 270) => handle_unsupported(), + (Pselect6 = 270) => do_pselect6(nfds: c_int, readfds: *mut libc::fd_set, writefds: *mut libc::fd_set, exceptfds: *mut libc::fd_set, timeout: *mut timespec_t, data: *const Pselect6sig), (Ppoll = 271) => do_ppoll(fds: *mut libc::pollfd, nfds: libc::nfds_t, timeout_ts: *const timespec_t, sigmask: *const sigset_t), (Unshare = 272) => handle_unsupported(), (SetRobustList = 273) => do_set_robust_list(list_head_ptr: *mut RobustListHead, len: usize),