diff --git a/Pal/src/host/Linux-SGX/db_main.c b/Pal/src/host/Linux-SGX/db_main.c index 42f27d2f..c76734d7 100644 --- a/Pal/src/host/Linux-SGX/db_main.c +++ b/Pal/src/host/Linux-SGX/db_main.c @@ -156,7 +156,7 @@ static const char** make_argv_list(void * uptr_src, uint64_t src_size) { return NULL; } - if (sgx_copy_to_enclave(data, uptr_src, src_size) != 0) { + if (!sgx_copy_to_enclave(data, src_size, uptr_src, src_size)) { goto free_and_err; } data[src_size - 1] = '\0'; @@ -211,7 +211,7 @@ void pal_linux_main(char * uptr_args, uint64_t args_size, int rv; struct pal_sec sec_info; - if (sgx_copy_to_enclave(&sec_info, uptr_sec_info, sizeof(sec_info)) != 0) { + if (!sgx_copy_to_enclave(&sec_info, sizeof(sec_info), uptr_sec_info, sizeof(sec_info))) { return; } diff --git a/Pal/src/host/Linux-SGX/enclave_framework.c b/Pal/src/host/Linux-SGX/enclave_framework.c index aa50c007..316f6539 100644 --- a/Pal/src/host/Linux-SGX/enclave_framework.c +++ b/Pal/src/host/Linux-SGX/enclave_framework.c @@ -38,21 +38,8 @@ bool sgx_is_completely_outside_enclave(const void* addr, uint64_t size) { return enclave_base >= addr + size || enclave_top <= addr; } -__attribute__((warn_unused_result)) -int sgx_copy_to_enclave(void * dst, void * uptr_src, uint64_t size) { - if (!sgx_is_completely_outside_enclave(uptr_src, size) || - !sgx_is_completely_within_enclave(dst, size)) { - return -PAL_ERROR_DENIED; - } - - memcpy(dst, uptr_src, size); - - return 0; -} - -void * sgx_ocalloc (uint64_t size) -{ - void * ustack = GET_ENCLAVE_TLS(ustack) - size; +void* sgx_alloc_on_ustack(uint64_t size) { + void* ustack = GET_ENCLAVE_TLS(ustack) - size; if (!sgx_is_completely_outside_enclave(ustack, size)) { return NULL; } @@ -60,11 +47,49 @@ void * sgx_ocalloc (uint64_t size) return ustack; } -void sgx_ocfree (void) -{ +void* sgx_copy_to_ustack(const void* ptr, uint64_t size) { + if (!sgx_is_completely_within_enclave(ptr, size)) { + return NULL; + } + void* uptr = sgx_alloc_on_ustack(size); + if (uptr) { + memcpy(uptr, ptr, size); + } + return uptr; +} + +void sgx_reset_ustack(void) { SET_ENCLAVE_TLS(ustack, GET_ENCLAVE_TLS(ustack_top)); } +/* NOTE: Value from possibly untrusted uptr must be copied inside + * CPU register or enclave stack (to prevent TOCTOU). Function call + * achieves this. Attribute ensures no inline optimization. */ +__attribute__((noinline)) +bool sgx_copy_ptr_to_enclave(void** ptr, void* uptr, uint64_t size) { + assert(ptr); + if (!sgx_is_completely_outside_enclave(uptr, size)) { + *ptr = NULL; + return false; + } + *ptr = uptr; + return true; +} + +/* NOTE: Value from possibly untrusted uptr and usize must be copied + * inside CPU registers or enclave stack (to prevent TOCTOU). Function + * call achieves this. Attribute ensures no inline optimization. */ +__attribute__((noinline)) +uint64_t sgx_copy_to_enclave(const void* ptr, uint64_t maxsize, const void* uptr, uint64_t usize) { + if (usize > maxsize || + !sgx_is_completely_outside_enclave(uptr, usize) || + !sgx_is_completely_within_enclave(ptr, usize)) { + return 0; + } + memcpy((void*) ptr, uptr, usize); + return usize; +} + int sgx_get_report (sgx_arch_hash_t * mrenclave, sgx_arch_attributes_t * attributes, void * enclave_data, diff --git a/Pal/src/host/Linux-SGX/enclave_ocalls.c b/Pal/src/host/Linux-SGX/enclave_ocalls.c index 7d0e4e3e..a4d2075b 100644 --- a/Pal/src/host/Linux-SGX/enclave_ocalls.c +++ b/Pal/src/host/Linux-SGX/enclave_ocalls.c @@ -12,58 +12,8 @@ #include "ocall_types.h" #include "ecall_types.h" #include - #include -#define OCALLOC(val, type, len) do { \ - void * _tmp = sgx_ocalloc(len); \ - if (_tmp == NULL) { \ - OCALL_EXIT(); \ - return -EPERM; /* TODO: remove this control-flow obfuscation */ \ - } \ - (val) = (type) _tmp; \ -} while (0) - -int printf(const char * fmt, ...); - -#define SGX_OCALL(code, ms) sgx_ocall(code, ms) - -#define OCALL_EXIT() \ - do { \ - sgx_ocfree(); \ - } while (0) - -#define ALLOC_IN_USER(ptr, size) \ - ({ \ - __typeof__(ptr) tmp = ptr; \ - if (!sgx_is_completely_outside_enclave(ptr, size)) { \ - OCALLOC(tmp, __typeof__(tmp), size); \ - }; tmp; \ - }) - -#define COPY_TO_USER(ptr, size) \ - ({ \ - __typeof__(ptr) tmp = ptr; \ - if (!sgx_is_completely_outside_enclave(ptr, size)) { \ - OCALLOC(tmp, __typeof__(tmp), size); \ - memcpy((void *) tmp, ptr, size); \ - }; tmp; \ - }) - -#define COPY_FROM_USER(var, user_var, size) \ - ({ \ - int _ret = 0; \ - if (var != user_var) { \ - if (sgx_is_completely_outside_enclave(user_var, size) && \ - sgx_is_completely_within_enclave(var, size)) { \ - _ret = 0; \ - memcpy(var, user_var, size); \ - } else { \ - _ret = -EPERM; \ - } \ - } _ret; \ - }) - int ocall_exit(int exitcode) { int64_t code = exitcode; @@ -72,7 +22,7 @@ int ocall_exit(int exitcode) // 2. We can't trust the outside to actually exit, so we need to ensure // that we never return even when the outside tries to trick us. while (true) { - SGX_OCALL(OCALL_EXIT, (void *) code); + sgx_ocall(OCALL_EXIT, (void *) code); } return 0; } @@ -81,18 +31,29 @@ int ocall_print_string (const char * str, unsigned int length) { int retval = 0; ms_ocall_print_string_t * ms; - OCALLOC(ms, ms_ocall_print_string_t *, sizeof(*ms)); - if (!str || length <= 0) { - OCALL_EXIT(); + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); return -EPERM; } - ms->ms_str = COPY_TO_USER(str, length); - ms->ms_length = length; + if (!str || length <= 0) { + sgx_reset_ustack(); + return -EPERM; + } - retval = SGX_OCALL(OCALL_PRINT_STRING, ms); - OCALL_EXIT(); + ms->ms_length = length; + ms->ms_str = sgx_copy_to_ustack(str, length); + + if (!ms->ms_str) { + sgx_reset_ustack(); + return -EPERM; + } + + retval = sgx_ocall(OCALL_PRINT_STRING, ms); + + sgx_reset_ustack(); return retval; } @@ -101,19 +62,24 @@ int ocall_alloc_untrusted (uint64_t size, void ** mem) int retval = 0; ms_ocall_alloc_untrusted_t * ms; - OCALLOC(ms, ms_ocall_alloc_untrusted_t *, sizeof(*ms)); + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } ms->ms_size = size; - retval = SGX_OCALL(OCALL_ALLOC_UNTRUSTED, ms); + retval = sgx_ocall(OCALL_ALLOC_UNTRUSTED, ms); + if (!retval) { - if (!sgx_is_completely_outside_enclave(ms->ms_mem, size)) { - OCALL_EXIT(); + if (!sgx_copy_ptr_to_enclave(mem, ms->ms_mem, size)) { + sgx_reset_ustack(); return -EPERM; } - *mem = ms->ms_mem; } - OCALL_EXIT(); + + sgx_reset_ustack(); return retval; } @@ -124,42 +90,52 @@ int ocall_map_untrusted (int fd, uint64_t offset, int retval = 0; ms_ocall_map_untrusted_t * ms; - OCALLOC(ms, ms_ocall_map_untrusted_t *, sizeof(*ms)); + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } ms->ms_fd = fd; ms->ms_offset = offset; ms->ms_size = size; ms->ms_prot = prot; - retval = SGX_OCALL(OCALL_MAP_UNTRUSTED, ms); + retval = sgx_ocall(OCALL_MAP_UNTRUSTED, ms); + if (!retval) { - if (!sgx_is_completely_outside_enclave(ms->ms_mem, size)) { - OCALL_EXIT(); + if (!sgx_copy_ptr_to_enclave(mem, ms->ms_mem, size)) { + sgx_reset_ustack(); return -EPERM; } - *mem = ms->ms_mem; } - OCALL_EXIT(); + + sgx_reset_ustack(); return retval; } int ocall_unmap_untrusted (const void * mem, uint64_t size) { int retval = 0; + ms_ocall_unmap_untrusted_t * ms; if (!sgx_is_completely_outside_enclave(mem, size)) { - OCALL_EXIT(); + sgx_reset_ustack(); return -EINVAL; } - ms_ocall_unmap_untrusted_t * ms; - OCALLOC(ms, ms_ocall_unmap_untrusted_t *, sizeof(*ms)); + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } ms->ms_mem = mem; ms->ms_size = size; - retval = SGX_OCALL(OCALL_UNMAP_UNTRUSTED, ms); - OCALL_EXIT(); + retval = sgx_ocall(OCALL_UNMAP_UNTRUSTED, ms); + + sgx_reset_ustack(); return retval; } @@ -168,12 +144,18 @@ int ocall_cpuid (unsigned int leaf, unsigned int subleaf, { int retval = 0; ms_ocall_cpuid_t * ms; - OCALLOC(ms, ms_ocall_cpuid_t *, sizeof(*ms)); + + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } ms->ms_leaf = leaf; ms->ms_subleaf = subleaf; - retval = SGX_OCALL(OCALL_CPUID, ms); + retval = sgx_ocall(OCALL_CPUID, ms); + if (!retval) { values[0] = ms->ms_values[0]; values[1] = ms->ms_values[1]; @@ -181,7 +163,7 @@ int ocall_cpuid (unsigned int leaf, unsigned int subleaf, values[3] = ms->ms_values[3]; } - OCALL_EXIT(); + sgx_reset_ustack(); return retval; } @@ -190,14 +172,25 @@ int ocall_open (const char * pathname, int flags, unsigned short mode) int retval = 0; int len = pathname ? strlen(pathname) + 1 : 0; ms_ocall_open_t * ms; - OCALLOC(ms, ms_ocall_open_t *, sizeof(*ms)); - ms->ms_pathname = COPY_TO_USER(pathname, len); + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } + ms->ms_flags = flags; ms->ms_mode = mode; + ms->ms_pathname = sgx_copy_to_ustack(pathname, len); - retval = SGX_OCALL(OCALL_OPEN, ms); - OCALL_EXIT(); + if (!ms->ms_pathname) { + sgx_reset_ustack(); + return -EPERM; + } + + retval = sgx_ocall(OCALL_OPEN, ms); + + sgx_reset_ustack(); return retval; } @@ -205,12 +198,18 @@ int ocall_close (int fd) { int retval = 0; ms_ocall_close_t *ms; - OCALLOC(ms, ms_ocall_close_t *, sizeof(*ms)); + + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } ms->ms_fd = fd; - retval = SGX_OCALL(OCALL_CLOSE, ms); - OCALL_EXIT(); + retval = sgx_ocall(OCALL_CLOSE, ms); + + sgx_reset_ustack(); return retval; } @@ -218,6 +217,7 @@ int ocall_read (int fd, void * buf, unsigned int count) { int retval = 0; void * obuf = NULL; + ms_ocall_read_t * ms; if (count > PRESET_PAGESIZE) { retval = ocall_alloc_untrusted(ALLOC_ALIGNUP(count), &obuf); @@ -225,25 +225,37 @@ int ocall_read (int fd, void * buf, unsigned int count) return retval; } - ms_ocall_read_t * ms; - OCALLOC(ms, ms_ocall_read_t *, sizeof(*ms)); + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + retval = -EPERM; + goto out; + } ms->ms_fd = fd; + ms->ms_count = count; if (obuf) ms->ms_buf = obuf; else - OCALLOC(ms->ms_buf, void *, count); - ms->ms_count = count; + ms->ms_buf = sgx_alloc_on_ustack(count); - retval = SGX_OCALL(OCALL_READ, ms); + if (!ms->ms_buf) { + retval = -EPERM; + goto out; + } - if (retval > 0) - memcpy(buf, ms->ms_buf, retval); - OCALL_EXIT(); + retval = sgx_ocall(OCALL_READ, ms); + if (retval > 0) { + if (!sgx_copy_to_enclave(buf, count, ms->ms_buf, retval)) { + retval = -EPERM; + goto out; + } + } + +out: + sgx_reset_ustack(); if (obuf) ocall_unmap_untrusted(obuf, ALLOC_ALIGNUP(count)); - return retval; } @@ -251,6 +263,7 @@ int ocall_write (int fd, const void * buf, unsigned int count) { int retval = 0; void * obuf = NULL; + ms_ocall_write_t * ms; if (count > PRESET_PAGESIZE) { retval = ocall_alloc_untrusted(ALLOC_ALIGNUP(count), &obuf); @@ -258,24 +271,32 @@ int ocall_write (int fd, const void * buf, unsigned int count) return retval; } - ms_ocall_write_t * ms; - OCALLOC(ms, ms_ocall_write_t *, sizeof(*ms)); + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + retval = -EPERM; + goto out; + } ms->ms_fd = fd; + ms->ms_count = count; if (obuf) { ms->ms_buf = obuf; memcpy(obuf, buf, count); } else { - ms->ms_buf = COPY_TO_USER(buf, count); + ms->ms_buf = sgx_copy_to_ustack(buf, count); } - ms->ms_count = count; - retval = SGX_OCALL(OCALL_WRITE, ms); - OCALL_EXIT(); + if (!ms->ms_buf) { + retval = -EPERM; + goto out; + } + retval = sgx_ocall(OCALL_WRITE, ms); + +out: + sgx_reset_ustack(); if (obuf) ocall_unmap_untrusted(obuf, ALLOC_ALIGNUP(count)); - return retval; } @@ -283,14 +304,22 @@ int ocall_fstat (int fd, struct stat * buf) { int retval = 0; ms_ocall_fstat_t * ms; - OCALLOC(ms, ms_ocall_fstat_t *, sizeof(*ms)); + + + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } ms->ms_fd = fd; - retval = SGX_OCALL(OCALL_FSTAT, ms); + retval = sgx_ocall(OCALL_FSTAT, ms); + if (!retval) memcpy(buf, &ms->ms_stat, sizeof(struct stat)); - OCALL_EXIT(); + + sgx_reset_ustack(); return retval; } @@ -298,12 +327,18 @@ int ocall_fionread (int fd) { int retval = 0; ms_ocall_fionread_t * ms; - OCALLOC(ms, ms_ocall_fionread_t *, sizeof(*ms)); + + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } ms->ms_fd = fd; - retval = SGX_OCALL(OCALL_FIONREAD, ms); - OCALL_EXIT(); + retval = sgx_ocall(OCALL_FIONREAD, ms); + + sgx_reset_ustack(); return retval; } @@ -311,13 +346,19 @@ int ocall_fsetnonblock (int fd, int nonblocking) { int retval = 0; ms_ocall_fsetnonblock_t * ms; - OCALLOC(ms, ms_ocall_fsetnonblock_t *, sizeof(*ms)); + + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } ms->ms_fd = fd; ms->ms_nonblocking = nonblocking; - retval = SGX_OCALL(OCALL_FSETNONBLOCK, ms); - OCALL_EXIT(); + retval = sgx_ocall(OCALL_FSETNONBLOCK, ms); + + sgx_reset_ustack(); return retval; } @@ -325,13 +366,19 @@ int ocall_fchmod (int fd, unsigned short mode) { int retval = 0; ms_ocall_fchmod_t * ms; - OCALLOC(ms, ms_ocall_fchmod_t *, sizeof(*ms)); + + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } ms->ms_fd = fd; ms->ms_mode = mode; - retval = SGX_OCALL(OCALL_FCHMOD, ms); - OCALL_EXIT(); + retval = sgx_ocall(OCALL_FCHMOD, ms); + + sgx_reset_ustack(); return retval; } @@ -339,12 +386,18 @@ int ocall_fsync (int fd) { int retval = 0; ms_ocall_fsync_t * ms; - OCALLOC(ms, ms_ocall_fsync_t *, sizeof(*ms)); + + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } ms->ms_fd = fd; - retval = SGX_OCALL(OCALL_FSYNC, ms); - OCALL_EXIT(); + retval = sgx_ocall(OCALL_FSYNC, ms); + + sgx_reset_ustack(); return retval; } @@ -352,13 +405,19 @@ int ocall_ftruncate (int fd, uint64_t length) { int retval = 0; ms_ocall_ftruncate_t * ms; - OCALLOC(ms, ms_ocall_ftruncate_t *, sizeof(*ms)); + + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } ms->ms_fd = fd; ms->ms_length = length; - retval = SGX_OCALL(OCALL_FTRUNCATE, ms); - OCALL_EXIT(); + retval = sgx_ocall(OCALL_FTRUNCATE, ms); + + sgx_reset_ustack(); return retval; } @@ -367,13 +426,24 @@ int ocall_mkdir (const char * pathname, unsigned short mode) int retval = 0; int len = pathname ? strlen(pathname) + 1 : 0; ms_ocall_mkdir_t * ms; - OCALLOC(ms, ms_ocall_mkdir_t *, sizeof(*ms)); - ms->ms_pathname = COPY_TO_USER(pathname, len); + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } + ms->ms_mode = mode; + ms->ms_pathname = sgx_copy_to_ustack(pathname, len); - retval = SGX_OCALL(OCALL_MKDIR, ms); - OCALL_EXIT(); + if (!ms->ms_pathname) { + sgx_reset_ustack(); + return -EPERM; + } + + retval = sgx_ocall(OCALL_MKDIR, ms); + + sgx_reset_ustack(); return retval; } @@ -381,22 +451,38 @@ int ocall_getdents (int fd, struct linux_dirent64 * dirp, unsigned int size) { int retval = 0; ms_ocall_getdents_t * ms; - OCALLOC(ms, ms_ocall_getdents_t *, sizeof(*ms)); + + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } ms->ms_fd = fd; - ms->ms_dirp = ALLOC_IN_USER(dirp, size); ms->ms_size = size; + ms->ms_dirp = sgx_alloc_on_ustack(size); - retval = SGX_OCALL(OCALL_GETDENTS, ms); - if (retval > 0) - COPY_FROM_USER(dirp, ms->ms_dirp, retval); - OCALL_EXIT(); + if (!ms->ms_dirp) { + sgx_reset_ustack(); + return -EPERM; + } + + retval = sgx_ocall(OCALL_GETDENTS, ms); + + if (retval > 0) { + if (!sgx_copy_to_enclave(dirp, size, ms->ms_dirp, retval)) { + sgx_reset_ustack(); + return -EPERM; + } + } + + sgx_reset_ustack(); return retval; } int ocall_wake_thread (void * tcs) { - return SGX_OCALL(OCALL_WAKE_THREAD, tcs); + return sgx_ocall(OCALL_WAKE_THREAD, tcs); } int ocall_create_process (const char * uri, @@ -407,17 +493,32 @@ int ocall_create_process (const char * uri, int retval = 0; int ulen = uri ? strlen(uri) + 1 : 0; ms_ocall_create_process_t * ms; - OCALLOC(ms, ms_ocall_create_process_t *, - sizeof(*ms) + sizeof(const char *) * nargs); - ms->ms_uri = uri ? COPY_TO_USER(uri, ulen) : NULL; + ms = sgx_alloc_on_ustack(sizeof(*ms) + nargs * sizeof(char *)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } + + ms->ms_uri = uri ? sgx_copy_to_ustack(uri, ulen) : NULL; + if (uri && !ms->ms_uri) { + sgx_reset_ustack(); + return -EPERM; + } + ms->ms_nargs = nargs; for (int i = 0 ; i < nargs ; i++) { int len = args[i] ? strlen(args[i]) + 1 : 0; - ms->ms_args[i] = args[i] ? COPY_TO_USER(args[i], len) : NULL; + ms->ms_args[i] = args[i] ? sgx_copy_to_ustack(args[i], len) : NULL; + + if (args[i] && !ms->ms_args[i]) { + sgx_reset_ustack(); + return -EPERM; + } } - retval = SGX_OCALL(OCALL_CREATE_PROCESS, ms); + retval = sgx_ocall(OCALL_CREATE_PROCESS, ms); + if (!retval) { if (pid) *pid = ms->ms_pid; @@ -425,7 +526,8 @@ int ocall_create_process (const char * uri, procfds[1] = ms->ms_proc_fds[1]; procfds[2] = ms->ms_proc_fds[2]; } - OCALL_EXIT(); + + sgx_reset_ustack(); return retval; } @@ -434,20 +536,26 @@ int ocall_futex (int * futex, int op, int val, { int retval = 0; ms_ocall_futex_t * ms; - OCALLOC(ms, ms_ocall_futex_t *, sizeof(*ms)); if (!sgx_is_completely_outside_enclave(futex, sizeof(int))) { - OCALL_EXIT(); + sgx_reset_ustack(); return -EINVAL; } + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } + ms->ms_futex = futex; ms->ms_op = op; ms->ms_val = val; ms->ms_timeout = timeout ? *timeout : OCALL_NO_TIMEOUT; - retval = SGX_OCALL(OCALL_FUTEX, ms); - OCALL_EXIT(); + retval = sgx_ocall(OCALL_FUTEX, ms); + + sgx_reset_ustack(); return retval; } @@ -456,18 +564,25 @@ int ocall_socketpair (int domain, int type, int protocol, { int retval = 0; ms_ocall_socketpair_t * ms; - OCALLOC(ms, ms_ocall_socketpair_t *, sizeof(*ms)); + + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } ms->ms_domain = domain; ms->ms_type = type; ms->ms_protocol = protocol; - retval = SGX_OCALL(OCALL_SOCKETPAIR, ms); + retval = sgx_ocall(OCALL_SOCKETPAIR, ms); + if (!retval) { sockfds[0] = ms->ms_sockfds[0]; sockfds[1] = ms->ms_sockfds[1]; } - OCALL_EXIT(); + + sgx_reset_ustack(); return retval; } @@ -476,33 +591,45 @@ int ocall_sock_listen (int domain, int type, int protocol, struct sockopt * sockopt) { int retval = 0; - unsigned int bind_len = *addrlen; + unsigned int copied; + unsigned int len = addrlen ? *addrlen : 0; ms_ocall_sock_listen_t * ms; - OCALLOC(ms, ms_ocall_sock_listen_t *, sizeof(*ms)); + + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } ms->ms_domain = domain; ms->ms_type = type; ms->ms_protocol = protocol; - ms->ms_addr = COPY_TO_USER(addr, bind_len); - ms->ms_addrlen = bind_len; + ms->ms_addrlen = len; + ms->ms_addr = (addr && len) ? sgx_copy_to_ustack(addr, len) : NULL; - retval = SGX_OCALL(OCALL_SOCK_LISTEN, ms); - if (retval >= 0) { - if (addrlen && ( - !sgx_is_completely_outside_enclave(ms->ms_addr, bind_len) || - ms->ms_addrlen > bind_len)) { - OCALL_EXIT(); - return -EPERM; - } - - if (addr) { - COPY_FROM_USER(addr, ms->ms_addr, ms->ms_addrlen); - *addrlen = ms->ms_addrlen; - } - if (sockopt) - *sockopt = ms->ms_sockopt; + if (addr && len && !ms->ms_addr) { + sgx_reset_ustack(); + return -EPERM; } - OCALL_EXIT(); + + retval = sgx_ocall(OCALL_SOCK_LISTEN, ms); + + if (retval >= 0) { + if (addr && len) { + copied = sgx_copy_to_enclave(addr, len, ms->ms_addr, ms->ms_addrlen); + if (!copied) { + sgx_reset_ustack(); + return -EPERM; + } + *addrlen = copied; + } + + if (sockopt) { + *sockopt = ms->ms_sockopt; + } + } + + sgx_reset_ustack(); return retval; } @@ -510,30 +637,43 @@ int ocall_sock_accept (int sockfd, struct sockaddr * addr, unsigned int * addrlen, struct sockopt * sockopt) { int retval = 0; + unsigned int copied; unsigned int len = addrlen ? *addrlen : 0; ms_ocall_sock_accept_t * ms; - OCALLOC(ms, ms_ocall_sock_accept_t *, sizeof(*ms)); + + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } ms->ms_sockfd = sockfd; - ms->ms_addr = COPY_TO_USER(addr, len); ms->ms_addrlen = len; + ms->ms_addr = (addr && len) ? sgx_copy_to_ustack(addr, len) : NULL; - retval = SGX_OCALL(OCALL_SOCK_ACCEPT, ms); - if (retval >= 0) { - if (len && (!sgx_is_completely_outside_enclave(ms->ms_addr, len) || - ms->ms_addrlen > len)) { - OCALL_EXIT(); - return -EPERM; - } - - if (addr) { - COPY_FROM_USER(addr, ms->ms_addr, ms->ms_addrlen); - *addrlen = ms->ms_addrlen; - } - if (sockopt) - *sockopt = ms->ms_sockopt; + if (addr && len && !ms->ms_addr) { + sgx_reset_ustack(); + return -EPERM; } - OCALL_EXIT(); + + retval = sgx_ocall(OCALL_SOCK_ACCEPT, ms); + + if (retval >= 0) { + if (addr && len) { + copied = sgx_copy_to_enclave(addr, len, ms->ms_addr, ms->ms_addrlen); + if (!copied) { + sgx_reset_ustack(); + return -EPERM; + } + *addrlen = copied; + } + + if (sockopt) { + *sockopt = ms->ms_sockopt; + } + } + + sgx_reset_ustack(); return retval; } @@ -544,36 +684,47 @@ int ocall_sock_connect (int domain, int type, int protocol, unsigned int * bind_addrlen, struct sockopt * sockopt) { int retval = 0; + unsigned int copied; unsigned int bind_len = bind_addrlen ? *bind_addrlen : 0; ms_ocall_sock_connect_t * ms; - OCALLOC(ms, ms_ocall_sock_connect_t *, sizeof(*ms)); + + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } ms->ms_domain = domain; ms->ms_type = type; ms->ms_protocol = protocol; - ms->ms_addr = COPY_TO_USER(addr, addrlen); ms->ms_addrlen = addrlen; - ms->ms_bind_addr = bind_addr ? COPY_TO_USER(bind_addr, bind_len) : NULL; ms->ms_bind_addrlen = bind_len; + ms->ms_addr = addr ? sgx_copy_to_ustack(addr, addrlen) : NULL; + ms->ms_bind_addr = bind_addr ? sgx_copy_to_ustack(bind_addr, bind_len) : NULL; - retval = SGX_OCALL(OCALL_SOCK_CONNECT, ms); - if (retval >= 0) { - if (bind_len && ( - !sgx_is_completely_outside_enclave(ms->ms_bind_addr, bind_len) || - ms->ms_bind_addrlen > bind_len)) { - OCALL_EXIT(); - return -EPERM; - } - - if (bind_addr) { - COPY_FROM_USER(bind_addr, ms->ms_bind_addr, - ms->ms_bind_addrlen); - *bind_addrlen = ms->ms_bind_addrlen; - } - if (sockopt) - *sockopt = ms->ms_sockopt; + if ((addr && !ms->ms_addr) || (bind_addr && !ms->ms_bind_addr)) { + sgx_reset_ustack(); + return -EPERM; } - OCALL_EXIT(); + + retval = sgx_ocall(OCALL_SOCK_CONNECT, ms); + + if (retval >= 0) { + if (bind_addr && bind_len) { + copied = sgx_copy_to_enclave(bind_addr, bind_len, ms->ms_bind_addr, ms->ms_bind_addrlen); + if (!copied) { + sgx_reset_ustack(); + return -EPERM; + } + *bind_addrlen = copied; + } + + if (sockopt) { + *sockopt = ms->ms_sockopt; + } + } + + sgx_reset_ustack(); return retval; } @@ -581,47 +732,59 @@ int ocall_sock_recv (int sockfd, void * buf, unsigned int count, struct sockaddr * addr, unsigned int * addrlen) { int retval = 0; - void *obuf = NULL; + void * obuf = NULL; + unsigned int copied; unsigned int len = addrlen ? *addrlen : 0; + ms_ocall_sock_recv_t * ms; if ((count + len) > PRESET_PAGESIZE) { retval = ocall_alloc_untrusted(ALLOC_ALIGNUP(count), &obuf); - if (retval < 0) + if (IS_ERR(retval)) return retval; } - ms_ocall_sock_recv_t * ms; - OCALLOC(ms, ms_ocall_sock_recv_t *, sizeof(*ms)); + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + retval = -EPERM; + goto out; + } ms->ms_sockfd = sockfd; + ms->ms_count = count; + ms->ms_addrlen = len; + ms->ms_addr = addr ? sgx_alloc_on_ustack(len) : NULL; 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; + ms->ms_buf = sgx_alloc_on_ustack(count); - retval = SGX_OCALL(OCALL_SOCK_RECV, ms); - if (retval >= 0) { - if (len && (!sgx_is_completely_outside_enclave(ms->ms_addr, len) || - ms->ms_addrlen > len)) { - retval = -EPERM; - goto done; - } - - COPY_FROM_USER(buf, ms->ms_buf, retval); - COPY_FROM_USER(addr, ms->ms_addr, ms->ms_addrlen); - if (addrlen) - *addrlen = ms->ms_addrlen; + if (!ms->ms_buf || (addr && !ms->ms_addr)) { + retval = -EPERM; + goto out; } -done: - OCALL_EXIT(); + retval = sgx_ocall(OCALL_SOCK_RECV, ms); + if (retval >= 0) { + if (addr && len) { + copied = sgx_copy_to_enclave(addr, len, ms->ms_addr, ms->ms_addrlen); + if (!copied) { + retval = -EPERM; + goto out; + } + *addrlen = copied; + } + + if (!sgx_copy_to_enclave(buf, count, ms->ms_buf, retval)) { + retval = -EPERM; + goto out; + } + } + +out: + sgx_reset_ustack(); if (obuf) ocall_unmap_untrusted(obuf, ALLOC_ALIGNUP(count)); - return retval; } @@ -629,34 +792,43 @@ 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; + void * obuf = NULL; + ms_ocall_sock_send_t * ms; if ((count + addrlen) > PRESET_PAGESIZE) { retval = ocall_alloc_untrusted(ALLOC_ALIGNUP(count), &obuf); - if (retval < 0) + if (IS_ERR(retval)) return retval; } - ms_ocall_sock_send_t * ms; - OCALLOC(ms, ms_ocall_sock_send_t *, sizeof(*ms)); + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + retval = -EPERM; + goto out; + } ms->ms_sockfd = sockfd; + ms->ms_count = count; + ms->ms_addrlen = addrlen; + ms->ms_addr = addr ? sgx_copy_to_ustack(addr, addrlen) : NULL; if (obuf) { ms->ms_buf = obuf; memcpy(obuf, buf, count); } else { - ms->ms_buf = COPY_TO_USER(buf, count); + ms->ms_buf = sgx_copy_to_ustack(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 (!ms->ms_buf || (addr && !ms->ms_addr)) { + retval = -EPERM; + goto out; + } + retval = sgx_ocall(OCALL_SOCK_SEND, ms); + +out: + sgx_reset_ustack(); if (obuf) ocall_unmap_untrusted(obuf, ALLOC_ALIGNUP(count)); - return retval; } @@ -664,28 +836,44 @@ int ocall_sock_recv_fd (int sockfd, void * buf, unsigned int count, unsigned int * fds, unsigned int * nfds) { int retval = 0; + unsigned int copied; + unsigned int max_nfds_bytes = (*nfds) * sizeof(int); ms_ocall_sock_recv_fd_t * ms; - OCALLOC(ms, ms_ocall_sock_recv_fd_t *, sizeof(*ms)); + + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } ms->ms_sockfd = sockfd; - ms->ms_buf = ALLOC_IN_USER(buf, count); ms->ms_count = count; - ms->ms_fds = fds ? ALLOC_IN_USER(fds, sizeof(int) * (*nfds)) : NULL; ms->ms_nfds = *nfds; + ms->ms_buf = sgx_alloc_on_ustack(count); + ms->ms_fds = sgx_alloc_on_ustack(max_nfds_bytes); + + if (!ms->ms_buf || !ms->ms_fds) { + sgx_reset_ustack(); + return -EPERM; + } + + retval = sgx_ocall(OCALL_SOCK_RECV_FD, ms); - retval = SGX_OCALL(OCALL_SOCK_RECV_FD, ms); if (retval >= 0) { - if (!sgx_is_completely_outside_enclave(ms->ms_fds, sizeof(int) * (*nfds)) || - ms->ms_nfds > (*nfds)) { - OCALL_EXIT(); + if (!sgx_copy_to_enclave(buf, count, ms->ms_buf, retval)) { + sgx_reset_ustack(); return -EPERM; } - COPY_FROM_USER(buf, ms->ms_buf, retval); - COPY_FROM_USER(fds, ms->ms_fds, sizeof(int) * ms->ms_nfds); - *nfds = ms->ms_nfds; + copied = sgx_copy_to_enclave(fds, max_nfds_bytes, ms->ms_fds, ms->ms_nfds * sizeof(int)); + if (!copied) { + sgx_reset_ustack(); + return -EPERM; + } + *nfds = copied / sizeof(int); } - OCALL_EXIT(); + + sgx_reset_ustack(); return retval; } @@ -694,16 +882,27 @@ int ocall_sock_send_fd (int sockfd, const void * buf, unsigned int count, { int retval = 0; ms_ocall_sock_send_fd_t * ms; - OCALLOC(ms, ms_ocall_sock_send_fd_t *, sizeof(*ms)); + + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } ms->ms_sockfd = sockfd; - ms->ms_buf = COPY_TO_USER(buf, count); ms->ms_count = count; - ms->ms_fds = fds ? COPY_TO_USER(fds, sizeof(int) * nfds) : NULL; ms->ms_nfds = nfds; + ms->ms_buf = sgx_copy_to_ustack(buf, count); + ms->ms_fds = sgx_copy_to_ustack(fds, nfds * sizeof(int)); - retval = SGX_OCALL(OCALL_SOCK_SEND_FD, ms); - OCALL_EXIT(); + if (!ms->ms_buf || !ms->ms_fds) { + sgx_reset_ustack(); + return -EPERM; + } + + retval = sgx_ocall(OCALL_SOCK_SEND_FD, ms); + + sgx_reset_ustack(); return retval; } @@ -712,16 +911,32 @@ int ocall_sock_setopt (int sockfd, int level, int optname, { int retval = 0; ms_ocall_sock_setopt_t * ms; - OCALLOC(ms, ms_ocall_sock_setopt_t *, sizeof(*ms)); + + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } ms->ms_sockfd = sockfd; ms->ms_level = level; ms->ms_optname = optname; - ms->ms_optval = COPY_TO_USER(optval, optlen); - ms->ms_optlen = optlen; + ms->ms_optlen = 0; + ms->ms_optval = NULL; - retval = SGX_OCALL(OCALL_SOCK_SETOPT, ms); - OCALL_EXIT(); + if (optval && optlen > 0) { + ms->ms_optlen = optlen; + ms->ms_optval = sgx_copy_to_ustack(optval, optlen); + + if (!ms->ms_optval) { + sgx_reset_ustack(); + return -EPERM; + } + } + + retval = sgx_ocall(OCALL_SOCK_SETOPT, ms); + + sgx_reset_ustack(); return retval; } @@ -729,13 +944,19 @@ int ocall_sock_shutdown (int sockfd, int how) { int retval = 0; ms_ocall_sock_shutdown_t * ms; - OCALLOC(ms, ms_ocall_sock_shutdown_t *, sizeof(*ms)); + + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } ms->ms_sockfd = sockfd; ms->ms_how = how; - retval = SGX_OCALL(OCALL_SOCK_SHUTDOWN, ms); - OCALL_EXIT(); + retval = sgx_ocall(OCALL_SOCK_SHUTDOWN, ms); + + sgx_reset_ustack(); return retval; } @@ -743,12 +964,18 @@ int ocall_gettime (unsigned long * microsec) { int retval = 0; ms_ocall_gettime_t * ms; - OCALLOC(ms, ms_ocall_gettime_t *, sizeof(*ms)); - retval = SGX_OCALL(OCALL_GETTIME, ms); + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } + + retval = sgx_ocall(OCALL_GETTIME, ms); if (!retval) *microsec = ms->ms_microsec; - OCALL_EXIT(); + + sgx_reset_ustack(); return retval; } @@ -756,37 +983,61 @@ int ocall_sleep (unsigned long * microsec) { int retval = 0; ms_ocall_sleep_t * ms; - OCALLOC(ms, ms_ocall_sleep_t *, sizeof(*ms)); + + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } ms->ms_microsec = microsec ? *microsec : 0; - retval = SGX_OCALL(OCALL_SLEEP, ms); + retval = sgx_ocall(OCALL_SLEEP, ms); if (microsec) { if (!retval) *microsec = 0; else if (retval == -EINTR) *microsec = ms->ms_microsec; } - OCALL_EXIT(); + + sgx_reset_ustack(); return retval; } int ocall_poll (struct pollfd * fds, int nfds, uint64_t * timeout) { int retval = 0; + unsigned int nfds_bytes = nfds * sizeof(struct pollfd); ms_ocall_poll_t * ms; - OCALLOC(ms, ms_ocall_poll_t *, sizeof(*ms)); - ms->ms_fds = COPY_TO_USER(fds, sizeof(struct pollfd) * nfds); + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } + ms->ms_nfds = nfds; ms->ms_timeout = timeout ? *timeout : OCALL_NO_TIMEOUT; + ms->ms_fds = sgx_copy_to_ustack(fds, nfds_bytes); + + if (!ms->ms_fds) { + sgx_reset_ustack(); + return -EPERM; + } + + retval = sgx_ocall(OCALL_POLL, ms); - retval = SGX_OCALL(OCALL_POLL, ms); if (retval == -EINTR && timeout) *timeout = ms->ms_timeout; - if (retval >= 0) - COPY_FROM_USER(fds, ms->ms_fds, sizeof(struct pollfd) * nfds); - OCALL_EXIT(); + + if (retval >= 0) { + if (!sgx_copy_to_enclave(fds, nfds_bytes, ms->ms_fds, nfds_bytes)) { + sgx_reset_ustack(); + return -EPERM; + } + } + + sgx_reset_ustack(); return retval; } @@ -796,13 +1047,24 @@ int ocall_rename (const char * oldpath, const char * newpath) int oldlen = oldpath ? strlen(oldpath) + 1 : 0; int newlen = newpath ? strlen(newpath) + 1 : 0; ms_ocall_rename_t * ms; - OCALLOC(ms, ms_ocall_rename_t *, sizeof(*ms)); - ms->ms_oldpath = COPY_TO_USER(oldpath, oldlen); - ms->ms_newpath = COPY_TO_USER(newpath, newlen); + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } - retval = SGX_OCALL(OCALL_RENAME, ms); - OCALL_EXIT(); + ms->ms_oldpath = sgx_copy_to_ustack(oldpath, oldlen); + ms->ms_newpath = sgx_copy_to_ustack(newpath, newlen); + + if (!ms->ms_oldpath || !ms->ms_newpath) { + sgx_reset_ustack(); + return -EPERM; + } + + retval = sgx_ocall(OCALL_RENAME, ms); + + sgx_reset_ustack(); return retval; } @@ -811,21 +1073,38 @@ int ocall_delete (const char * pathname) int retval = 0; int len = pathname ? strlen(pathname) + 1 : 0; ms_ocall_delete_t * ms; - OCALLOC(ms, ms_ocall_delete_t *, sizeof(*ms)); - ms->ms_pathname = COPY_TO_USER(pathname, len); + ms = sgx_alloc_on_ustack(sizeof(*ms)); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } - retval = SGX_OCALL(OCALL_DELETE, ms); - OCALL_EXIT(); + ms->ms_pathname = sgx_copy_to_ustack(pathname, len); + if (!ms->ms_pathname) { + sgx_reset_ustack(); + return -EPERM; + } + + retval = sgx_ocall(OCALL_DELETE, ms); + + sgx_reset_ustack(); return retval; } int ocall_load_debug(const char * command) { int retval = 0; - int len = strlen(command); - const char * ms = COPY_TO_USER(command, len + 1); - retval = SGX_OCALL(OCALL_LOAD_DEBUG, (void *) ms); - OCALL_EXIT(); + int len = strlen(command) + 1; + + const char * ms = sgx_copy_to_ustack(command, len); + if (!ms) { + sgx_reset_ustack(); + return -EPERM; + } + + retval = sgx_ocall(OCALL_LOAD_DEBUG, (void *) ms); + + sgx_reset_ustack(); return retval; } diff --git a/Pal/src/host/Linux-SGX/sgx_api.h b/Pal/src/host/Linux-SGX/sgx_api.h index ab02f0ae..6898e256 100644 --- a/Pal/src/host/Linux-SGX/sgx_api.h +++ b/Pal/src/host/Linux-SGX/sgx_api.h @@ -24,13 +24,15 @@ int sgx_ocall (unsigned long code, void * ms); -void * sgx_ocalloc (uint64_t size); -void sgx_ocfree (void); - bool sgx_is_completely_within_enclave (const void * addr, uint64_t size); bool sgx_is_completely_outside_enclave(const void * addr, uint64_t size); -int sgx_copy_to_enclave(void * dst, void * uptr_src, uint64_t size); +void* sgx_alloc_on_ustack(uint64_t size); +void* sgx_copy_to_ustack(const void* ptr, uint64_t size); +void sgx_reset_ustack(void); + +bool sgx_copy_ptr_to_enclave(void** ptr, void* uptr, uint64_t size); +uint64_t sgx_copy_to_enclave(const void* ptr, uint64_t maxsize, const void* uptr, uint64_t usize); int sgx_report (sgx_arch_targetinfo_t * targetinfo, void * reportdata, sgx_arch_report_t * report);