Skip to content

Commit

Permalink
[libos] Implement Pselect syscall with sigset
Browse files Browse the repository at this point in the history
  • Loading branch information
ClawSeven committed Dec 19, 2023
1 parent cc89edc commit d962322
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 5 deletions.
105 changes: 104 additions & 1 deletion src/libos/src/net/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<isize> {
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::<sigset_t>() {
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,
Expand Down
3 changes: 2 additions & 1 deletion src/libos/src/signal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -34,3 +34,4 @@ mod signals;
mod syscalls;

pub mod constants;
pub mod do_sigprocmask;
7 changes: 4 additions & 3 deletions src/libos/src/syscall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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),
Expand Down

0 comments on commit d962322

Please sign in to comment.