Pass host-generated SIGPIPE to libos

Socket-related ocalls, e.g, sendto, sendmsg and write, may cause SIGPIPE
in host. Since the ocall is called by libos, this kind of signal should
be handled in libos. We ignore SIGPIPE in host and raise the same signal
in libos if the return value of the above ocalls is EPIPE. In this way
the signal is handled by libos.
This commit is contained in:
He Sun 2020-09-14 17:15:48 +08:00 committed by Tate, Hongliang Tian
parent 44583e15be
commit 5d5e8d44ec
6 changed files with 41 additions and 17 deletions

@ -51,3 +51,20 @@ macro_rules! try_libc {
ret
}};
}
// return Err(errno) if libc return -1
// raise SIGPIPE if errno == EPIPE
macro_rules! try_libc_may_epipe {
($ret: expr) => {{
let ret = unsafe { $ret };
if ret < 0 {
let errno = unsafe { libc::errno() };
if errno == Errno::EPIPE as i32 {
// SIGPIPE = 12
crate::signal::do_tkill(current!().tid(), 12);
}
return_errno!(Errno::from(errno as u32), "libc error");
}
ret
}};
}

@ -59,7 +59,7 @@ impl File for SocketFile {
fn write(&self, buf: &[u8]) -> Result<usize> {
let (buf_ptr, buf_len) = buf.as_ptr_and_len();
let ret = try_libc!(libc::ocall::write(
let ret = try_libc_may_epipe!(libc::ocall::write(
self.host_fd,
buf_ptr as *const c_void,
buf_len

@ -56,10 +56,10 @@ impl SocketFile {
let (msg_control, msg_controllen) = control.as_ptr_and_len();
let msg_control = msg_control as *const c_void;
// Flags
let flags = flags.bits();
let raw_flags = flags.bits();
let bytes_sent = try_libc!({
// Do OCall
// Do OCall
unsafe {
let status = occlum_ocall_sendmsg(
&mut retval as *mut isize,
host_fd,
@ -69,12 +69,17 @@ impl SocketFile {
msg_iovlen,
msg_control,
msg_controllen,
flags,
raw_flags,
);
assert!(status == sgx_status_t::SGX_SUCCESS);
}
let bytes_sent = if flags.contains(SendFlags::MSG_NOSIGNAL) {
try_libc!(retval)
} else {
try_libc_may_epipe!(retval)
};
retval
});
debug_assert!(bytes_sent >= 0);
Ok(bytes_sent as usize)
}

@ -286,7 +286,7 @@ pub fn do_sendto(
let file_ref = current!().file(fd as FileDesc)?;
if let Ok(socket) = file_ref.as_socket() {
// TODO: check addr and addr_len according to connection mode
let ret = try_libc!(libc::ocall::sendto(
let ret = try_libc_may_epipe!(libc::ocall::sendto(
socket.fd(),
base,
len,

@ -36,12 +36,10 @@ int occlum_pal_init(const struct occlum_pal_attr *attr) {
errno = EEXIST;
return -1;
}
// FIXME
#ifndef SGX_MODE_SIM
if (pal_register_sig_handlers() < 0) {
return -1;
}
#endif
if (pal_init_enclave(resolved_path) < 0) {
return -1;

@ -7,12 +7,16 @@
#define SIGRT_INTERRUPT 64
int pal_register_sig_handlers(void) {
struct sigaction action;
action.sa_handler = SIG_IGN;
memset(&action.sa_mask, 0, sizeof(action.sa_mask));
action.sa_flags = 0;
if (sigaction(SIGRT_INTERRUPT, &action, NULL) < 0) {
PAL_ERROR("Failed to regiter signal handlers");
// FIXME: enable interruptable signal in SIM mode
#ifndef SGX_MODE_SIM
if (signal(SIGRT_INTERRUPT, SIG_IGN) == SIG_ERR) {
PAL_ERROR("Failed to regiter the SIG64 handler");
return -1;
}
#endif
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
PAL_ERROR("Failed to regiter the SIGPIPE handler");
return -1;
}
return 0;