mirror of
https://github.com/clearlinux/graphene.git
synced 2026-09-06 05:41:37 +00:00
[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:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user