Skip to content

Commit

Permalink
[PAL/Linux-SGX] Print a nice error if enclave range collides with oth…
Browse files Browse the repository at this point in the history
…er regions

Previously, if enclave size was very large (e.g. 2TB) its collision with
some hardcoded memory regions in untrusted memory (ASan shadow map,
debug info area, untrusted shared memory) caused allocation failures,
leading to cryptic errors.
This commit fixes that and checks all the ranges for collisions.

The lack of these checks was _not_ a security issue, because:
- ASan range is used only in debug builds
- debug range is used also in release, but only by the untrusted PAL
- shared memory range allocation would fail in ocall_mmap_untrusted()
  before leaving the enclave (on pointer check)

Signed-off-by: Michał Kowalczyk <mkow@invisiblethingslab.com>
  • Loading branch information
mkow authored and dimakuv committed Apr 9, 2024
1 parent bbc4068 commit a9f7d1c
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 0 deletions.
10 changes: 10 additions & 0 deletions common/include/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,16 @@ int buf_flush(struct print_buf* buf);
#define TIME_NS_IN_US 1000ul
#define TIME_NS_IN_S (TIME_NS_IN_US * TIME_US_IN_S)

/* ranges are inclusive-exclusive - [start, end) */
static inline bool ranges_overlap(uintptr_t a_start, uintptr_t a_end,
uintptr_t b_start, uintptr_t b_end) {
assert(a_start <= a_end);
assert(b_start <= b_end);
if (a_start == a_end || b_start == b_end)
return false; // an empty range doesn't overlap with anything
return !(a_end <= b_start || b_end <= a_start);
}

#ifdef __x86_64__
static inline bool __range_not_ok(uintptr_t addr, size_t size) {
addr += size;
Expand Down
21 changes: 21 additions & 0 deletions pal/src/host/linux-sgx/host_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,27 @@ static int initialize_enclave(struct pal_enclave* enclave, const char* manifest_
enclave->baseaddr = DEFAULT_ENCLAVE_BASE;
enclave_heap_min = MMAP_MIN_ADDR;

/* Print a user-friendly error if enclave range overlaps with some hardcoded regions in
* untrusted memory. */
if (ranges_overlap(enclave->baseaddr, enclave->baseaddr + enclave->size,
SHARED_ADDR_MIN, SHARED_ADDR_MIN + SHARED_MEM_SIZE)
|| ranges_overlap(enclave->baseaddr, enclave->baseaddr + enclave->size,
DBGINFO_ADDR, DBGINFO_ADDR + sizeof(struct enclave_dbginfo))) {
log_error("Enclave range collides with shared memory or debug range. Consider reducing "
"enclave size.");
ret = -EINVAL;
goto out;

}
#ifdef ASAN
if (ranges_overlap(enclave->baseaddr, enclave->baseaddr + enclave->size,
ASAN_SHADOW_START, ASAN_SHADOW_START + ASAN_SHADOW_LENGTH)) {
log_error("Enclave range collides with ASan range. Consider reducing enclave size.");
ret = -EINVAL;
goto out;
}
#endif

sig_path = alloc_concat(g_pal_enclave.application_path, -1, ".sig", -1);
if (!sig_path) {
ret = -ENOMEM;
Expand Down
8 changes: 8 additions & 0 deletions pal/src/host/linux-sgx/pal_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,14 @@ noreturn void pal_linux_main(void* uptr_libpal_uri, size_t libpal_uri_len, void*
g_pal_public_state.memory_address_start = g_pal_linuxsgx_state.heap_min;
g_pal_public_state.memory_address_end = g_pal_linuxsgx_state.heap_max;

if (ranges_overlap((uintptr_t)g_enclave_base, (uintptr_t)g_enclave_top,
SHARED_ADDR_MIN, SHARED_ADDR_MIN + SHARED_MEM_SIZE)
|| ranges_overlap((uintptr_t)g_enclave_base, (uintptr_t)g_enclave_top,
DBGINFO_ADDR, DBGINFO_ADDR + sizeof(struct enclave_dbginfo))) {
/* This should have been already checked by untrusted PAL with a more descriptive error */
log_error("Enclave overlaps with some hardcoded regions");
ocall_exit(1, /*is_exitgroup=*/true);
}
static_assert(SHARED_ADDR_MIN >= DBGINFO_ADDR + sizeof(struct enclave_dbginfo)
|| DBGINFO_ADDR >= SHARED_ADDR_MIN + SHARED_MEM_SIZE,
"SHARED_ADDR overlaps with DBGINFO_ADDR");
Expand Down

0 comments on commit a9f7d1c

Please sign in to comment.