From 4b8f74a8d83a5eadaea2b59ec8afa33a42adf3a3 Mon Sep 17 00:00:00 2001 From: smherwig Date: Sat, 26 Jan 2019 21:12:34 -0500 Subject: [PATCH] [PAL/Linux-SGX] Allow ocall_sock_send/recv to allocate on heap ocall_sock_recv/send copied/allocated buffers on untrusted stack. If buffer sizes were large, the stack overflowed. This patch allocates buffers on untrusted heap if size is too large. --- Pal/src/host/Linux-SGX/enclave_ocalls.c | 42 ++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/Pal/src/host/Linux-SGX/enclave_ocalls.c b/Pal/src/host/Linux-SGX/enclave_ocalls.c index b2326f7d..7f9dc626 100644 --- a/Pal/src/host/Linux-SGX/enclave_ocalls.c +++ b/Pal/src/host/Linux-SGX/enclave_ocalls.c @@ -581,12 +581,23 @@ int ocall_sock_recv (int sockfd, void * buf, unsigned int count, struct sockaddr * addr, unsigned int * addrlen) { int retval = 0; + void *obuf = NULL; unsigned int len = addrlen ? *addrlen : 0; + + if ((count + len) > 4096) { + retval = ocall_alloc_untrusted(ALLOC_ALIGNUP(count), &obuf); + if (retval < 0) + return retval; + } + ms_ocall_sock_recv_t * ms; OCALLOC(ms, ms_ocall_sock_recv_t *, sizeof(*ms)); ms->ms_sockfd = sockfd; - ms->ms_buf = ALLOC_IN_USER(buf, count); + if (obuf) + ms->ms_buf = obuf; + else + ms->ms_buf = ALLOC_IN_USER(buf, count); ms->ms_count = count; ms->ms_addr = addr ? ALLOC_IN_USER(addr, len) : NULL; ms->ms_addrlen = len; @@ -595,8 +606,8 @@ int ocall_sock_recv (int sockfd, void * buf, unsigned int count, if (retval >= 0) { if (len && (!sgx_is_completely_outside_enclave(ms->ms_addr, len) || ms->ms_addrlen > len)) { - OCALL_EXIT(); - return -EPERM; + retval = -EPERM; + goto done; } COPY_FROM_USER(buf, ms->ms_buf, retval); @@ -604,7 +615,13 @@ int ocall_sock_recv (int sockfd, void * buf, unsigned int count, if (addrlen) *addrlen = ms->ms_addrlen; } + +done: OCALL_EXIT(); + + if (obuf) + ocall_unmap_untrusted(obuf, ALLOC_ALIGNUP(count)); + return retval; } @@ -612,17 +629,34 @@ int ocall_sock_send (int sockfd, const void * buf, unsigned int count, const struct sockaddr * addr, unsigned int addrlen) { int retval = 0; + void *obuf = NULL; + + if ((count + addrlen) > 4096) { + retval = ocall_alloc_untrusted(ALLOC_ALIGNUP(count), &obuf); + if (retval < 0) + return retval; + } + ms_ocall_sock_send_t * ms; OCALLOC(ms, ms_ocall_sock_send_t *, sizeof(*ms)); ms->ms_sockfd = sockfd; - ms->ms_buf = COPY_TO_USER(buf, count); + if (obuf) { + ms->ms_buf = obuf; + memcpy(obuf, buf, count); + } else { + ms->ms_buf = COPY_TO_USER(buf, count); + } ms->ms_count = count; ms->ms_addr = addr ? COPY_TO_USER(addr, addrlen) : NULL; ms->ms_addrlen = addrlen; retval = SGX_OCALL(OCALL_SOCK_SEND, ms); OCALL_EXIT(); + + if (obuf) + ocall_unmap_untrusted(obuf, ALLOC_ALIGNUP(count)); + return retval; }