diff --git a/Pal/src/host/Linux-SGX/enclave_ocalls.c b/Pal/src/host/Linux-SGX/enclave_ocalls.c index 70c78f36..5c70b2af 100644 --- a/Pal/src/host/Linux-SGX/enclave_ocalls.c +++ b/Pal/src/host/Linux-SGX/enclave_ocalls.c @@ -266,10 +266,21 @@ int ocall_write (int fd, const void * buf, unsigned int count) void * obuf = NULL; ms_ocall_write_t * ms; - if (count > PRESET_PAGESIZE) { - retval = ocall_alloc_untrusted(ALLOC_ALIGNUP(count), &obuf); - if (IS_ERR(retval)) - return retval; + if (sgx_is_completely_outside_enclave(buf, count)) { + /* buf is in untrusted memory (e.g., allowed file mmaped in untrusted memory) */ + obuf = (void*)buf; + } else if (sgx_is_completely_within_enclave(buf, count)) { + /* typical case of buf inside of enclave memory */ + if (count > PRESET_PAGESIZE) { + /* buf is too big and may overflow untrusted stack, so use untrusted heap */ + retval = ocall_alloc_untrusted(ALLOC_ALIGNUP(count), &obuf); + if (IS_ERR(retval)) + return retval; + memcpy(obuf, buf, count); + } + } else { + /* buf is partially in/out of enclave memory */ + return -EPERM; } ms = sgx_alloc_on_ustack(sizeof(*ms)); @@ -280,12 +291,10 @@ int ocall_write (int fd, const void * buf, unsigned int count) ms->ms_fd = fd; ms->ms_count = count; - if (obuf) { + if (obuf) ms->ms_buf = obuf; - memcpy(obuf, buf, count); - } else { + else ms->ms_buf = sgx_copy_to_ustack(buf, count); - } if (!ms->ms_buf) { retval = -EPERM; @@ -296,7 +305,7 @@ int ocall_write (int fd, const void * buf, unsigned int count) out: sgx_reset_ustack(); - if (obuf) + if (obuf && obuf != buf) ocall_unmap_untrusted(obuf, ALLOC_ALIGNUP(count)); return retval; } @@ -791,10 +800,21 @@ int ocall_sock_send (int sockfd, const void * buf, unsigned int count, void * obuf = NULL; ms_ocall_sock_send_t * ms; - if ((count + addrlen) > PRESET_PAGESIZE) { - retval = ocall_alloc_untrusted(ALLOC_ALIGNUP(count), &obuf); - if (IS_ERR(retval)) - return retval; + if (sgx_is_completely_outside_enclave(buf, count)) { + /* buf is in untrusted memory (e.g., allowed file mmaped in untrusted memory) */ + obuf = (void*)buf; + } else if (sgx_is_completely_within_enclave(buf, count)) { + /* typical case of buf inside of enclave memory */ + if ((count + addrlen) > PRESET_PAGESIZE) { + /* buf is too big and may overflow untrusted stack, so use untrusted heap */ + retval = ocall_alloc_untrusted(ALLOC_ALIGNUP(count), &obuf); + if (IS_ERR(retval)) + return retval; + memcpy(obuf, buf, count); + } + } else { + /* buf is partially in/out of enclave memory */ + return -EPERM; } ms = sgx_alloc_on_ustack(sizeof(*ms)); @@ -807,12 +827,10 @@ int ocall_sock_send (int sockfd, const void * buf, unsigned int count, ms->ms_count = count; ms->ms_addrlen = addrlen; ms->ms_addr = addr ? sgx_copy_to_ustack(addr, addrlen) : NULL; - if (obuf) { + if (obuf) ms->ms_buf = obuf; - memcpy(obuf, buf, count); - } else { + else ms->ms_buf = sgx_copy_to_ustack(buf, count); - } if (!ms->ms_buf || (addr && !ms->ms_addr)) { retval = -EPERM; @@ -823,7 +841,7 @@ int ocall_sock_send (int sockfd, const void * buf, unsigned int count, out: sgx_reset_ustack(); - if (obuf) + if (obuf && obuf != buf) ocall_unmap_untrusted(obuf, ALLOC_ALIGNUP(count)); return retval; }