From 5d5e8d44ecae49ac1a426585ec9c8340f650b6ff Mon Sep 17 00:00:00 2001 From: He Sun Date: Mon, 14 Sep 2020 17:15:48 +0800 Subject: [PATCH] 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. --- src/libos/src/error/mod.rs | 17 +++++++++++++++++ src/libos/src/net/socket_file/mod.rs | 2 +- src/libos/src/net/socket_file/send.rs | 17 +++++++++++------ src/libos/src/net/syscalls.rs | 2 +- src/pal/src/pal_api.c | 4 +--- src/pal/src/pal_sig_handler.c | 16 ++++++++++------ 6 files changed, 41 insertions(+), 17 deletions(-) diff --git a/src/libos/src/error/mod.rs b/src/libos/src/error/mod.rs index 14bc33ab..e01eff8c 100644 --- a/src/libos/src/error/mod.rs +++ b/src/libos/src/error/mod.rs @@ -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 + }}; +} diff --git a/src/libos/src/net/socket_file/mod.rs b/src/libos/src/net/socket_file/mod.rs index 88721761..243e8d77 100644 --- a/src/libos/src/net/socket_file/mod.rs +++ b/src/libos/src/net/socket_file/mod.rs @@ -59,7 +59,7 @@ impl File for SocketFile { fn write(&self, buf: &[u8]) -> Result { 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 diff --git a/src/libos/src/net/socket_file/send.rs b/src/libos/src/net/socket_file/send.rs index 7d5d98d3..d3594633 100644 --- a/src/libos/src/net/socket_file/send.rs +++ b/src/libos/src/net/socket_file/send.rs @@ -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) } diff --git a/src/libos/src/net/syscalls.rs b/src/libos/src/net/syscalls.rs index fa91e513..94ecdeeb 100644 --- a/src/libos/src/net/syscalls.rs +++ b/src/libos/src/net/syscalls.rs @@ -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, diff --git a/src/pal/src/pal_api.c b/src/pal/src/pal_api.c index d10ea308..1d043571 100644 --- a/src/pal/src/pal_api.c +++ b/src/pal/src/pal_api.c @@ -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; diff --git a/src/pal/src/pal_sig_handler.c b/src/pal/src/pal_sig_handler.c index 995c6b37..108236fd 100644 --- a/src/pal/src/pal_sig_handler.c +++ b/src/pal/src/pal_sig_handler.c @@ -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;