[Pal/Linux-SGX] Allow ocall_mmap_untrusted() with fixed address

This functionality is currently not used by Linux-SGX PAL but will be
required in the IOCTL emulation in future commits.
This commit is contained in:
Dmitrii Kuvaiskii
2020-12-07 07:03:43 -08:00
parent b430a27dae
commit e77de77fcd
6 changed files with 53 additions and 23 deletions
+1 -1
View File
@@ -412,7 +412,6 @@ static int file_map(PAL_HANDLE handle, void** addr, int prot, uint64_t offset, u
sgx_stub_t* stubs = (sgx_stub_t*)handle->file.stubs;
uint64_t total = handle->file.total;
void* mem = *addr;
void* umem;
int ret;
/*
@@ -451,6 +450,7 @@ static int file_map(PAL_HANDLE handle, void** addr, int prot, uint64_t offset, u
map_end = ALLOC_ALIGN_UP(end);
}
void* umem = NULL;
ret = ocall_mmap_untrusted(handle->file.fd, map_start, map_end - map_start, PROT_READ, &umem);
if (IS_ERR(ret)) {
SGX_DBG(DBG_E, "file_map - ocall returned %d\n", ret);
+2 -2
View File
@@ -145,7 +145,7 @@ void _DkDebugAddMap(struct link_map* map) {
shdr = __alloca(shdrsz);
unsigned long s = ALLOC_ALIGN_DOWN(ehdr->e_shoff);
unsigned long e = ALLOC_ALIGN_UP(ehdr->e_shoff + shdrsz);
void* umem;
void* umem = NULL;
ocall_mmap_untrusted(fd, s, e - s, PROT_READ, &umem);
memcpy(shdr, umem + ehdr->e_shoff - s, shdrsz);
ocall_munmap_untrusted(umem, e - s);
@@ -167,7 +167,7 @@ void _DkDebugAddMap(struct link_map* map) {
shstrtab = __alloca(shstrsz);
unsigned long s = ALLOC_ALIGN_DOWN(shstroff);
unsigned long e = ALLOC_ALIGN_UP(shstroff + shstrsz);
void* umem;
void* umem = NULL;
ocall_mmap_untrusted(fd, s, e - s, PROT_READ, &umem);
memcpy((void*)shstrtab, umem + shstroff - s, shstrsz);
ocall_munmap_untrusted(umem, e - s);
+1 -1
View File
@@ -359,7 +359,7 @@ int load_trusted_file(PAL_HANDLE file, sgx_stub_t** stubptr, uint64_t* sizeptr,
* caller's responsibility to unmap those areas after use */
*sizeptr = tf->size;
if (*sizeptr) {
ret = ocall_mmap_untrusted(fd, 0, tf->size, PROT_READ, umem);
ret = ocall_mmap_untrusted(fd, /*offset=*/0, tf->size, PROT_READ, umem);
if (IS_ERR(ret)) {
*umem = NULL;
ret = unix_to_pal_error(ERRNO(ret));
+40 -10
View File
@@ -153,15 +153,38 @@ int ocall_mmap_untrusted(int fd, uint64_t offset, size_t size, unsigned short pr
return -EPERM;
}
if (!mem || (*mem && !sgx_is_completely_outside_enclave(*mem, size))) {
sgx_reset_ustack(old_ustack);
return -EINVAL;
}
if (*mem && !IS_ALLOC_ALIGNED_PTR(*mem)) {
/* fixed address must be correctly aligned */
sgx_reset_ustack(old_ustack);
return -EINVAL;
}
WRITE_ONCE(ms->ms_fd, fd);
WRITE_ONCE(ms->ms_offset, offset);
WRITE_ONCE(ms->ms_size, size);
WRITE_ONCE(ms->ms_prot, prot);
WRITE_ONCE(ms->ms_mem, *mem);
retval = sgx_exitless_ocall(OCALL_MMAP_UNTRUSTED, ms);
if (IS_ERR(retval) && !IS_UNIX_ERR(retval)) {
sgx_reset_ustack(old_ustack);
return -EPERM;
}
void* returned_mem = READ_ONCE(ms->ms_mem);
if (*mem && returned_mem != *mem) {
/* requested to mmap at a fixed address but OCALL returned another address */
sgx_reset_ustack(old_ustack);
return -EPERM;
}
if (!retval) {
if (!sgx_copy_ptr_to_enclave(mem, READ_ONCE(ms->ms_mem), size)) {
if (!sgx_copy_ptr_to_enclave(mem, returned_mem, size)) {
sgx_reset_ustack(old_ustack);
return -EPERM;
}
@@ -191,6 +214,8 @@ int ocall_munmap_untrusted(const void* mem, size_t size) {
WRITE_ONCE(ms->ms_size, size);
retval = sgx_exitless_ocall(OCALL_MUNMAP_UNTRUSTED, ms);
if (IS_ERR(retval) && !IS_UNIX_ERR(retval))
retval = -EPERM;
sgx_reset_ustack(old_ustack);
return retval;
@@ -209,15 +234,20 @@ int ocall_munmap_untrusted(const void* mem, size_t size) {
* indicates whether explicit munmap is needed at the end of such OCALL.
*/
static int ocall_mmap_untrusted_cache(size_t size, void** mem, bool* need_munmap) {
int ret;
*mem = NULL;
*need_munmap = false;
struct untrusted_area* cache = &get_tcb_trts()->untrusted_area_cache;
uint64_t in_use = 0;
if (!__atomic_compare_exchange_n(&cache->in_use, &in_use, 1, /*weak=*/false, __ATOMIC_RELAXED,
__ATOMIC_RELAXED)) {
/* AEX signal handling case: cache is in use, so make explicit mmap/munmap */
int retval = ocall_mmap_untrusted(-1, 0, size, PROT_READ | PROT_WRITE, mem);
if (IS_ERR(retval)) {
return retval;
ret = ocall_mmap_untrusted(/*fd=*/-1, /*offset=*/0, size, PROT_READ | PROT_WRITE, mem);
if (IS_ERR(ret)) {
return ret;
}
*need_munmap = true;
return 0;
@@ -229,16 +259,16 @@ static int ocall_mmap_untrusted_cache(size_t size, void** mem, bool* need_munmap
*mem = cache->mem;
return 0;
}
int retval = ocall_munmap_untrusted(cache->mem, cache->size);
if (IS_ERR(retval)) {
ret = ocall_munmap_untrusted(cache->mem, cache->size);
if (IS_ERR(ret)) {
cache->valid = false;
__atomic_store_n(&cache->in_use, 0, __ATOMIC_RELAXED);
return retval;
return ret;
}
}
int retval = ocall_mmap_untrusted(-1, 0, size, PROT_READ | PROT_WRITE, mem);
if (IS_ERR(retval)) {
ret = ocall_mmap_untrusted(/*fd=*/-1, /*offset=*/0, size, PROT_READ | PROT_WRITE, mem);
if (IS_ERR(ret)) {
cache->valid = false;
__atomic_store_n(&cache->in_use, 0, __ATOMIC_RELAXED);
} else {
@@ -246,7 +276,7 @@ static int ocall_mmap_untrusted_cache(size_t size, void** mem, bool* need_munmap
cache->mem = *mem;
cache->size = size;
}
return retval;
return ret;
}
static void ocall_munmap_untrusted_cache(void* mem, size_t size, bool need_munmap) {
+2 -3
View File
@@ -19,9 +19,8 @@ static size_t g_page_size = PRESET_PAGESIZE;
static inline void* __malloc(int size) {
void* addr = NULL;
ocall_mmap_untrusted(-1, 0, size, PROT_READ | PROT_WRITE, &addr);
return addr;
int ret = ocall_mmap_untrusted(/*fd=*/-1, /*offset=*/0, size, PROT_READ | PROT_WRITE, &addr);
return IS_ERR(ret) ? NULL : addr;
}
#define system_malloc(size) __malloc(size)
+7 -6
View File
@@ -90,13 +90,14 @@ static long sgx_ocall_exit(void* pms) {
static long sgx_ocall_mmap_untrusted(void* pms) {
ms_ocall_mmap_untrusted_t* ms = (ms_ocall_mmap_untrusted_t*)pms;
void* addr;
ODEBUG(OCALL_MMAP_UNTRUSTED, ms);
addr = (void*)INLINE_SYSCALL(mmap, 6, NULL, ms->ms_size,
ms->ms_prot,
(ms->ms_fd == -1) ? MAP_ANONYMOUS | MAP_PRIVATE
: MAP_FILE | MAP_SHARED,
ms->ms_fd, ms->ms_offset);
/* NOTE: enclave never asks for fixed address 0x0, so ms_mem == NULL means "no fixed addr" */
int flags = ms->ms_mem ? MAP_FIXED : 0;
flags |= (ms->ms_fd == -1) ? MAP_ANONYMOUS | MAP_PRIVATE : MAP_FILE | MAP_SHARED;
addr = (void*)INLINE_SYSCALL(mmap, 6, ms->ms_mem, ms->ms_size, ms->ms_prot, flags, ms->ms_fd,
ms->ms_offset);
if (IS_ERR_P(addr))
return -ERRNO_P(addr);