Skip to content

Commit

Permalink
[PAL] Use MAP_FIXED_NOREPLACE where possible
Browse files Browse the repository at this point in the history
Signed-off-by: Michał Kowalczyk <mkow@invisiblethingslab.com>
  • Loading branch information
mkow authored and dimakuv committed Oct 20, 2023
1 parent 6583385 commit 88474ca
Show file tree
Hide file tree
Showing 8 changed files with 37 additions and 26 deletions.
2 changes: 1 addition & 1 deletion common/include/asan.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
* - Make sure the program maps the shadow memory area at startup. This will be something like:
*
* mmap((void*)ASAN_SHADOW_START, ASAN_SHADOW_LENGTH, PROT_READ | PROT_WRITE,
* MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED,
* MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED_NOREPLACE,
* -1, 0);
*
* - Annotate all functions that shouldn't perform sanitized memory access with
Expand Down
5 changes: 5 additions & 0 deletions libos/src/libos_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,11 @@ static void parse_mmap_flags(struct print_buf* buf, va_list* ap) {
flags &= ~MAP_FIXED;
}

if (flags & MAP_FIXED_NOREPLACE) {
buf_puts(buf, "|MAP_FIXED_NOREPLACE");
flags &= ~MAP_FIXED_NOREPLACE;
}

#ifdef CONFIG_MMAP_ALLOW_UNINITIALIZED
if (flags & MAP_UNINITIALIZED) {
buf_puts(buf, "|MAP_UNINITIALIZED");
Expand Down
7 changes: 4 additions & 3 deletions pal/src/host/linux-sgx/enclave_ocalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ int ocall_mmap_untrusted(void** addrptr, size_t size, int prot, int flags, int f

void* requested_addr = *addrptr;

if (flags & MAP_FIXED) {
if (flags & MAP_FIXED || flags & MAP_FIXED_NOREPLACE) {
if (!sgx_is_valid_untrusted_ptr(requested_addr, size, PAGE_SIZE)) {
sgx_reset_ustack(old_ustack);
return -EINVAL;
Expand All @@ -216,15 +216,16 @@ int ocall_mmap_untrusted(void** addrptr, size_t size, int prot, int flags, int f

if (retval < 0) {
if (retval != -EACCES && retval != -EAGAIN && retval != -EBADF && retval != -EINVAL &&
retval != -ENFILE && retval != -ENODEV && retval != -ENOMEM && retval != -EPERM) {
retval != -ENFILE && retval != -ENODEV && retval != -ENOMEM && retval != -EEXIST &&
retval != -EPERM) {
retval = -EPERM;
}
sgx_reset_ustack(old_ustack);
return retval;
}

void* returned_addr = COPY_UNTRUSTED_VALUE(&ocall_mmap_args->addr);
if (flags & MAP_FIXED) {
if (flags & MAP_FIXED || flags & MAP_FIXED_NOREPLACE) {
/* addrptr already contains the mmap'ed address, no need to update it */
if (returned_addr != requested_addr) {
sgx_reset_ustack(old_ustack);
Expand Down
7 changes: 4 additions & 3 deletions pal/src/host/linux-sgx/host_framework.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ int create_enclave(sgx_arch_secs_t* secs, sgx_arch_token_t* token) {
#endif

uint64_t addr = DO_SYSCALL(mmap, request_mmap_addr, request_mmap_size,
PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_SHARED,
PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED_NOREPLACE | MAP_SHARED,
g_isgx_device, 0);
if (IS_PTR_ERR(addr)) {
int ret = PTR_TO_ERR(addr);
Expand All @@ -201,7 +201,6 @@ int create_enclave(sgx_arch_secs_t* secs, sgx_arch_token_t* token) {
log_error("Allocation of EPC memory failed: %s", unix_strerror(ret));
return ret;
}

assert(addr == request_mmap_addr);

struct sgx_enclave_create param = {
Expand Down Expand Up @@ -404,7 +403,9 @@ int add_pages_to_enclave(sgx_arch_secs_t* secs, void* addr, void* user_addr, uns
param.length -= added_size;
}

/* ask Intel SGX driver to actually mmap the added enclave pages */
/* ask Intel SGX driver to actually mmap the added enclave pages; we can't use
* MAP_FIXED_NOREPLACE here because we are overwriting a subset of enclave memory already
* allocated in create_enclave(), see mmap request there */
uint64_t mapped = DO_SYSCALL(mmap, addr, size, prot, MAP_FIXED | MAP_SHARED, g_isgx_device, 0);
if (IS_PTR_ERR(mapped)) {
ret = PTR_TO_ERR(mapped);
Expand Down
10 changes: 7 additions & 3 deletions pal/src/host/linux-sgx/host_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -572,10 +572,14 @@ static int initialize_enclave(struct pal_enclave* enclave, const char* manifest_
struct enclave_dbginfo* dbg = (void*)DO_SYSCALL(mmap, DBGINFO_ADDR,
sizeof(struct enclave_dbginfo),
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
MAP_PRIVATE | MAP_ANONYMOUS
| MAP_FIXED_NOREPLACE,
/*fd=*/-1,
/*offset=*/0);
if (IS_PTR_ERR(dbg)) {
log_warning("Cannot allocate debug information (GDB will not work)");
} else {
assert(dbg == (void*)DBGINFO_ADDR);
dbg->pid = g_host_pid;
dbg->base = enclave->baseaddr;
dbg->size = enclave->size;
Expand Down Expand Up @@ -1119,10 +1123,10 @@ __attribute((constructor(0)))
__attribute_no_sanitize_address
static void setup_asan(void) {
int prot = PROT_READ | PROT_WRITE;
int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED;
int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED_NOREPLACE;
void* addr = (void*)DO_SYSCALL(mmap, (void*)ASAN_SHADOW_START, ASAN_SHADOW_LENGTH, prot, flags,
/*fd=*/-1, /*offset=*/0);
if (IS_PTR_ERR(addr)) {
if (IS_PTR_ERR(addr) || addr != (void*)ASAN_SHADOW_START) {
int err = PTR_TO_ERR(addr);
log_error("asan: error setting up shadow memory: %s", unix_strerror(err));
DO_SYSCALL(exit_group, unix_to_pal_error(err));
Expand Down
2 changes: 1 addition & 1 deletion pal/src/host/linux/pal_files.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ static int file_delete(PAL_HANDLE handle, enum pal_delete_mode delete_mode) {
static int file_map(PAL_HANDLE handle, void* addr, pal_prot_flags_t prot, uint64_t offset,
uint64_t size) {
int fd = handle->file.fd;
int flags = PAL_MEM_FLAGS_TO_LINUX(prot) | (addr ? MAP_FIXED : 0);
int flags = PAL_MEM_FLAGS_TO_LINUX(prot) | (addr ? MAP_FIXED_NOREPLACE : 0);
int linux_prot = PAL_PROT_TO_LINUX(prot);

/* The memory will always be allocated with flag MAP_PRIVATE. */
Expand Down
4 changes: 2 additions & 2 deletions pal/src/host/linux/pal_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,10 @@ __attribute_no_stack_protector
__attribute_no_sanitize_address
static void setup_asan(void) {
int prot = PROT_READ | PROT_WRITE;
int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED;
int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED_NOREPLACE;
void* addr = (void*)DO_SYSCALL(mmap, (void*)ASAN_SHADOW_START, ASAN_SHADOW_LENGTH, prot, flags,
/*fd=*/-1, /*offset=*/0);
if (IS_PTR_ERR(addr)) {
if (IS_PTR_ERR(addr) || addr != (void*)ASAN_SHADOW_START) {
/* We are super early in the init sequence, TCB is not yet set, we probably should not call
* any logging functions. */
DO_SYSCALL(exit_group, PAL_ERROR_NOMEM);
Expand Down
26 changes: 13 additions & 13 deletions pal/src/host/linux/pal_memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,15 @@ int _PalVirtualMemoryAlloc(void* addr, size_t size, pal_prot_flags_t prot) {
int flags = PAL_MEM_FLAGS_TO_LINUX(prot);
int linux_prot = PAL_PROT_TO_LINUX(prot);

flags |= MAP_ANONYMOUS | MAP_FIXED;
addr = (void*)DO_SYSCALL(mmap, addr, size, linux_prot, flags, -1, 0);
flags |= MAP_ANONYMOUS | MAP_FIXED_NOREPLACE;
void* res_addr = (void*)DO_SYSCALL(mmap, addr, size, linux_prot, flags, -1, 0);

if (IS_PTR_ERR(addr)) {
return unix_to_pal_error(PTR_TO_ERR(addr));
if (IS_PTR_ERR(res_addr)) {
return unix_to_pal_error(PTR_TO_ERR(res_addr));
}

assert(res_addr == addr);

return 0;
}

Expand Down Expand Up @@ -166,13 +168,14 @@ int init_memory_bookkeeping(void) {
#endif
/* Allocate a guard page above the stack. We do not support further stack auto growth. */
void* ptr = (void*)(proc_maps_info.stack_top - PAGE_SIZE);
ptr = (void*)DO_SYSCALL(mmap, ptr, PAGE_SIZE, PROT_NONE,
MAP_FIXED_NOREPLACE | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (IS_PTR_ERR(ptr)) {
ret = PTR_TO_ERR(ptr);
void* mmap_ret = (void*)DO_SYSCALL(mmap, ptr, PAGE_SIZE, PROT_NONE,
MAP_FIXED_NOREPLACE | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (IS_PTR_ERR(mmap_ret)) {
ret = PTR_TO_ERR(mmap_ret);
log_error("failed to map a stack guard page: %s", unix_strerror(ret));
return unix_to_pal_error(ret);
}
assert(mmap_ret == ptr);
ret = pal_add_initial_range((uintptr_t)ptr, PAGE_SIZE, /*prot=*/0, "stack guard");
if (ret < 0) {
return ret;
Expand All @@ -191,12 +194,9 @@ int init_memory_bookkeeping(void) {
ptr = (void*)DO_SYSCALL(mmap, start_addr, PAGE_SIZE, PROT_NONE,
MAP_FIXED_NOREPLACE | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (!IS_PTR_ERR(ptr)) {
assert(ptr == (void*)start_addr);
DO_SYSCALL(munmap, ptr, g_pal_public_state.alloc_align);
/* Check returned pointer in case of older kernels, which do not support
* `MAP_FIXED_NOREPLACE`. */
if (ptr == (void*)start_addr) {
break;
}
break;
} else if (PTR_TO_ERR(ptr) == -EEXIST) {
break;
}
Expand Down

0 comments on commit 88474ca

Please sign in to comment.