From 14764fa52c620dbde6628355f9d2ffc9748f7f83 Mon Sep 17 00:00:00 2001 From: borysp Date: Fri, 13 Nov 2020 01:05:27 +0100 Subject: [PATCH] [Pal/Linux-SGX] Wait for handshake finish in querying of pipe handles If a poll is done on a pipe handle and TLS handshake is still in progress, poll might report that there is data available to be read from the handle, while in reality only available data is TLS handshake, which will not be visible to the caller of `pipe_attrquerybyhdl` (poll). --- Pal/src/host/Linux-SGX/db_object.c | 2 ++ Pal/src/host/Linux-SGX/db_pipes.c | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/Pal/src/host/Linux-SGX/db_object.c b/Pal/src/host/Linux-SGX/db_object.c index 9fefad51..1266e8d6 100644 --- a/Pal/src/host/Linux-SGX/db_object.c +++ b/Pal/src/host/Linux-SGX/db_object.c @@ -31,6 +31,8 @@ int _DkSynchronizationObjectWait(PAL_HANDLE handle, int64_t timeout_us) { return ops->wait(handle, timeout_us); } +/* TODO: this should take into account `handle->pipe.handshake_done`. For more details see + * "Pal/src/host/Linux-SGX/db_pipes.c". */ /* Wait for specific events on all handles in the handle array and return multiple events * (including errors) reported by the host. Return 0 on success, PAL error on failure. */ int _DkStreamsWaitEvents(size_t count, PAL_HANDLE* handle_array, PAL_FLG* events, diff --git a/Pal/src/host/Linux-SGX/db_pipes.c b/Pal/src/host/Linux-SGX/db_pipes.c index 605ff47c..7e4212c7 100644 --- a/Pal/src/host/Linux-SGX/db_pipes.c +++ b/Pal/src/host/Linux-SGX/db_pipes.c @@ -503,6 +503,11 @@ static int pipe_delete(PAL_HANDLE handle, int access) { ocall_shutdown(handle->pipeprv.fds[1], SHUT_WR); } } else { + /* This pipe might use a secure session, make sure all initial work is done. */ + while (!__atomic_load_n(&handle->pipe.handshake_done, __ATOMIC_ACQUIRE)) { + CPU_RELAX(); + } + /* other types of pipes have a single underlying FD, shut it down */ if (handle->pipe.fd != PAL_IDX_POISON) { ocall_shutdown(handle->pipe.fd, shutdown); @@ -552,6 +557,11 @@ static int pipe_attrquerybyhdl(PAL_HANDLE handle, PAL_STREAM_ATTR* attr) { attr->readable = ret >= 1 && (pfd[0].revents & (POLLIN | POLLERR | POLLHUP)) == POLLIN; attr->writable = ret >= 1 && (pfd[1].revents & (POLLOUT | POLLERR | POLLHUP)) == POLLOUT; } else { + /* This pipe might use a secure session, make sure all initial work is done. */ + while (!__atomic_load_n(&handle->pipe.handshake_done, __ATOMIC_ACQUIRE)) { + CPU_RELAX(); + } + /* for non-private pipes, both readable and writable are queried on the same fd */ short pfd_events = POLLIN; if (!IS_HANDLE_TYPE(handle, pipesrv)) { @@ -584,6 +594,13 @@ static int pipe_attrsetbyhdl(PAL_HANDLE handle, PAL_STREAM_ATTR* attr) { if (handle->generic.fds[0] == PAL_IDX_POISON) return -PAL_ERROR_BADHANDLE; + if (!IS_HANDLE_TYPE(handle, pipeprv)) { + /* This pipe might use a secure session, make sure all initial work is done. */ + while (!__atomic_load_n(&handle->pipe.handshake_done, __ATOMIC_ACQUIRE)) { + CPU_RELAX(); + } + } + PAL_BOL* nonblocking = (HANDLE_HDR(handle)->type == pal_type_pipeprv) ? &handle->pipeprv.nonblocking : &handle->pipe.nonblocking;