Skip to content

Commit

Permalink
Naive dynamic heap with EDMM
Browse files Browse the repository at this point in the history
This is the naive dynamic heap management with EDMM, which:
- EAUG on PAL heap page allocation.
- TRIM and EREMOVE on PAL heap page free.
  • Loading branch information
zhtlancer committed Aug 3, 2020
1 parent 1df82ea commit 4f2cfa0
Show file tree
Hide file tree
Showing 13 changed files with 276 additions and 2 deletions.
5 changes: 5 additions & 0 deletions Pal/src/host/Linux-SGX/db_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,15 @@ void pal_linux_main(char * uptr_args, uint64_t args_size,
return;
}

pal_sec.edmm_mode = sec_info.edmm_mode;
SGX_DBG(DBG_D, "EDMM mode %d\n", pal_sec.edmm_mode);

pal_sec.heap_min = GET_ENCLAVE_TLS(heap_min);
pal_sec.heap_max = GET_ENCLAVE_TLS(heap_max);
pal_sec.exec_addr = GET_ENCLAVE_TLS(exec_addr);
pal_sec.exec_size = GET_ENCLAVE_TLS(exec_size);

#if ENCLAVE_ZERO_HEAP
/* Zero the heap. We need to take care to not zero the exec area. */

void* zero1_start = pal_sec.heap_min;
Expand All @@ -226,6 +230,7 @@ void pal_linux_main(char * uptr_args, uint64_t args_size,

memset(zero1_start, 0, zero1_end - zero1_start);
memset(zero2_start, 0, zero2_end - zero2_start);
#endif

/* relocate PAL itself */
pal_map.l_addr = elf_machine_load_address();
Expand Down
52 changes: 52 additions & 0 deletions Pal/src/host/Linux-SGX/enclave_ocalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "rpc_queue.h"
#include "sgx_attest.h"
#include "spinlock.h"
#include "enclave_pages.h"

/* Check against this limit if the buffer to be allocated fits on the untrusted stack; if not,
* buffer will be allocated on untrusted heap. Conservatively set this limit to 1/4 of the
Expand Down Expand Up @@ -1482,3 +1483,54 @@ int ocall_get_quote(const sgx_spid_t* spid, bool linkable, const sgx_report_t* r
sgx_reset_ustack(old_ustack);
return retval;
}

int ocall_trim_epc_pages(struct sgx_range* rg)
{
void *old_ustack = sgx_prepare_ustack();
struct sgx_range* ms;
int rval = 0;

ms = sgx_alloc_on_ustack_aligned(sizeof(*ms), alignof(*ms));
if (!ms) {
rval = -ENOMEM;
goto out;
}
ms->start_addr = rg->start_addr;
ms->nr_pages = rg->nr_pages;

rval = sgx_ocall(OCALL_TRIM_EPC_PAGES, ms);

out:
sgx_reset_ustack(old_ustack);
return rval;
}

int ocall_notify_accept(struct sgx_range* rg)
{
void *old_ustack = sgx_prepare_ustack();
struct sgx_range* ms;
int rval = 0;

ms = sgx_alloc_on_ustack_aligned(sizeof(*ms), alignof(*ms));
if (!ms) {
rval = -ENOMEM;
goto out;
}
ms->start_addr = rg->start_addr;
ms->nr_pages = rg->nr_pages;

rval = sgx_ocall(OCALL_NOTIFY_ACCEPT, ms);

out:
sgx_reset_ustack(old_ustack);
return rval;
}

int ocall_remove_epc_page(void* addr)
{
int retval;

retval = sgx_ocall(OCALL_REMOVE_EPC_PAGE, addr);

return retval;
}
8 changes: 8 additions & 0 deletions Pal/src/host/Linux-SGX/enclave_ocalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <linux/poll.h>
#include <sys/types.h>

#include "gsgx.h"

noreturn void ocall_exit (int exitcode, int is_exitgroup);

int ocall_mmap_untrusted (int fd, uint64_t offset,
Expand Down Expand Up @@ -108,3 +110,9 @@ int ocall_eventfd (unsigned int initval, int flags);
*/
int ocall_get_quote(const sgx_spid_t* spid, bool linkable, const sgx_report_t* report,
const sgx_quote_nonce_t* nonce, char** quote, size_t* quote_len);

int ocall_trim_epc_pages(struct sgx_range* rg);

int ocall_notify_accept(struct sgx_range* rg);

int ocall_remove_epc_page (void* addr);
83 changes: 83 additions & 0 deletions Pal/src/host/Linux-SGX/enclave_pages.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "pal_internal.h"
#include "pal_linux.h"
#include "pal_security.h"
#include "gsgx.h"

struct atomic_int g_allocated_pages;

Expand Down Expand Up @@ -217,6 +218,79 @@ static void* __create_vma_and_merge(void* addr, size_t size, bool is_pal_interna
return addr;
}

#define SE_DECLSPEC_ALIGN(x) __attribute__((aligned(x)))

void get_edmm_page_range(void *addr, size_t size, bool executable);
void free_edmm_page_range(void *start, size_t size);

void free_edmm_page_range(void *start, size_t size)
{
void *addr = (void *)((uintptr_t)start & (~(PRESET_PAGESIZE-1)));
void *end = addr + size;
int rval = 0;
struct sgx_range rg;
SE_DECLSPEC_ALIGN(sizeof(sgx_arch_sec_info_t)) sgx_arch_sec_info_t si;

si.flags = SGX_SECINFO_FLAGS_TRIM | SGX_SECINFO_FLAGS_MODIFIED;
memset(&si.reserved, 0, sizeof(si.reserved));

rg.start_addr = (unsigned long) addr;
rg.nr_pages = size / PRESET_PAGESIZE;
rval = ocall_trim_epc_pages(&rg);
if (rval) {
SGX_DBG(DBG_E, "EPC trim page on [%p, %p) failed (%d)\n",
addr, end, rval);
/* TODO: error handling */
}

for ( ; addr < end; addr += PRESET_PAGESIZE)
sgx_accept(&si, addr);

rval = ocall_notify_accept(&rg);
if (rval) {
SGX_DBG(DBG_E, "EPC notify_accept on [%p, %p) failed (%d)\n",
addr, end, rval);
/* TODO: error handling */
}
}

void get_edmm_page_range(void *start, size_t size, bool executable)
{
uintptr_t lo = (uintptr_t)start;
uintptr_t addr = lo + size;
SE_DECLSPEC_ALIGN(sizeof(sgx_arch_sec_info_t)) sgx_arch_sec_info_t si;

si.flags = SGX_SECINFO_FLAGS_R | SGX_SECINFO_FLAGS_W
| SGX_SECINFO_FLAGS_REG | SGX_SECINFO_FLAGS_PENDING;
memset(&si.reserved, 0, sizeof(si.reserved));

SE_DECLSPEC_ALIGN(sizeof(sgx_arch_sec_info_t)) sgx_arch_sec_info_t smi = si;
smi.flags |= SGX_SECINFO_FLAGS_X;

while (lo < addr) {
int rval;
addr -= PRESET_PAGESIZE;

rval = sgx_accept(&si, (const void *)addr);

if (rval) {
//SGX_DBG(DBG_E, "EDMM accept page failed: %p %d\n", (void *)addr, rval);
/* TODO: Need error handling here */
}

if (executable) {

rval = sgx_modpe(&smi, (const void *)addr);

if (rval) {
//SGX_DBG(DBG_E, "EDMM modpe page failed: %p %d\n", (void *)addr, rval);
/* TODO: Need error handling here */
}
}
}

}

void* get_enclave_pages(void* addr, size_t size, bool is_pal_internal) {
void* ret = NULL;

Expand Down Expand Up @@ -269,6 +343,11 @@ void* get_enclave_pages(void* addr, size_t size, bool is_pal_internal) {

out:
_DkInternalUnlock(&g_heap_vma_lock);

/* Allocate dynamic enclave pages for EDMM */
if (pal_sec.edmm_mode && ret) {
get_edmm_page_range(ret, size, 1);
}
return ret;
}

Expand All @@ -287,6 +366,10 @@ int free_enclave_pages(void* addr, size_t size) {

SGX_DBG(DBG_M, "Freeing %lu bytes in enclave memory at %p\n", size, addr);

if (pal_sec.edmm_mode == SGX_EDMM_MODE_NAIVE) {
free_edmm_page_range(addr, size);
}

_DkInternalLock(&g_heap_vma_lock);

/* VMA list contains both normal and pal-internal VMAs; it is impossible to free an area
Expand Down
3 changes: 3 additions & 0 deletions Pal/src/host/Linux-SGX/ocall_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ enum {
OCALL_LOAD_DEBUG,
OCALL_EVENTFD,
OCALL_GET_QUOTE,
OCALL_TRIM_EPC_PAGES,
OCALL_NOTIFY_ACCEPT,
OCALL_REMOVE_EPC_PAGE,
OCALL_NR,
};

Expand Down
2 changes: 2 additions & 0 deletions Pal/src/host/Linux-SGX/pal_linux_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

//#define USE_AES_NI 1

#define ENCLAVE_ZERO_HEAP 0

#define PRINT_ENCLAVE_STAT 0

#define MAX_ARGS_SIZE 10000000
Expand Down
8 changes: 8 additions & 0 deletions Pal/src/host/Linux-SGX/pal_security.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#define PAL_SECURITY_H

#include "pal.h"
#include "pal-arch.h"
#include "sgx_arch.h"

typedef char PAL_SEC_STR[255];
Expand Down Expand Up @@ -46,6 +47,13 @@ struct pal_sec {
#if PRINT_ENCLAVE_STAT == 1
PAL_NUM start_time;
#endif

/* EDMM mode
* 0: disabled
* 1: naive EDMM
* other values reserved for future use
*/
PAL_FLG edmm_mode;
};

#ifdef IN_ENCLAVE
Expand Down
32 changes: 32 additions & 0 deletions Pal/src/host/Linux-SGX/sgx_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,38 @@ static inline int64_t sgx_getkey(sgx_key_request_t* keyrequest, sgx_key_128bit_t
return rax;
}

/*!
* \brief Low-level wrapper around EACCEPT instruction leaf.
*
* Caller is responsible for parameter alignment: 64B for si
* and page size (4KiB) for addr.
*/
static inline int64_t sgx_accept(sgx_arch_sec_info_t* si, const void* addr) {
int64_t rax = EACCEPT;
__asm__ volatile(
ENCLU "\n"
: "+a"(rax)
: "b"(si), "c"(addr)
: "memory");
return rax;
}

/*!
* \brief Low-level wrapper around EMODPE instruction leaf.
*
* Caller is responsible for parameter alignment: 64B for si
* and page size (4KiB) for addr.
*/
static inline int64_t sgx_modpe(sgx_arch_sec_info_t* si, const void* addr) {
int64_t rax = EMODPE;
__asm__ volatile(
ENCLU "\n"
: "+a"(rax)
: "b"(si), "c"(addr)
: "memory");
return rax;
}

/*!
* \brief Low-level wrapper around RDRAND instruction (get hardware-generated random value).
*/
Expand Down
11 changes: 11 additions & 0 deletions Pal/src/host/Linux-SGX/sgx_arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ typedef uint8_t sgx_isvfamily_id_t[SGX_ISV_FAMILY_ID_SIZE];
#define SGX_FLAGS_PROVISION_KEY 0x10ULL
#define SGX_FLAGS_LICENSE_KEY 0x20ULL

#define SGX_EDMM_MODE_NOEDMM 0x0U
#define SGX_EDMM_MODE_NAIVE 0x1U

#define SGX_XFRM_LEGACY 0x03ULL
#define SGX_XFRM_AVX 0x06ULL
#define SGX_XFRM_MPX 0x18ULL
Expand Down Expand Up @@ -200,6 +203,12 @@ typedef struct {
#define SGX_SECINFO_FLAGS_SECS 0x000
#define SGX_SECINFO_FLAGS_TCS 0x100
#define SGX_SECINFO_FLAGS_REG 0x200
#define SGX_SECINFO_FLAGS_TRIM 0x400

/* EDMM Page status */
#define SGX_SECINFO_FLAGS_PENDING 0x008
#define SGX_SECINFO_FLAGS_MODIFIED 0x010
#define SGX_SECINFO_FLAGS_PR 0x020

typedef struct _css_header_t {
uint8_t header[12];
Expand Down Expand Up @@ -359,6 +368,8 @@ typedef uint8_t sgx_key_128bit_t[16];
#define EREPORT 0
#define EGETKEY 1
#define EEXIT 4
#define EACCEPT 5
#define EMODPE 6

#define LAUNCH_KEY 0
#define PROVISION_KEY 1
Expand Down
36 changes: 36 additions & 0 deletions Pal/src/host/Linux-SGX/sgx_enclave.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "sgx_enclave.h"
#include "sgx_internal.h"
#include "sgx_tls.h"
#include "gsgx.h"

#include <asm/errno.h>
#include <asm/ioctls.h>
Expand Down Expand Up @@ -664,6 +665,38 @@ static long sgx_ocall_get_quote(void* pms) {
&ms->ms_quote, &ms->ms_quote_len);
}

extern int g_isgx_device;
static long sgx_ocall_trim_epc_pages(void *pms) {
int retval = 0;
struct sgx_range *rg = (struct sgx_range *)pms;

retval = INLINE_SYSCALL(ioctl, 3, g_isgx_device, SGX_IOC_ENCLAVE_TRIM,
rg);

return retval;
}

static long sgx_ocall_notify_accept(void *pms) {
int retval = 0;
struct sgx_range *rg = (struct sgx_range *)pms;

retval = INLINE_SYSCALL(ioctl, 3, g_isgx_device, SGX_IOC_ENCLAVE_NOTIFY_ACCEPT,
rg);

return retval;
}

static long sgx_ocall_remove_epc_page(void *pms)
{
void *addr = pms;
int retval = 0;

retval = INLINE_SYSCALL(ioctl, 3, g_isgx_device, SGX_IOC_ENCLAVE_PAGE_REMOVE,
&addr);

return retval;
}

sgx_ocall_fn_t ocall_table[OCALL_NR] = {
[OCALL_EXIT] = sgx_ocall_exit,
[OCALL_MMAP_UNTRUSTED] = sgx_ocall_mmap_untrusted,
Expand Down Expand Up @@ -703,6 +736,9 @@ sgx_ocall_fn_t ocall_table[OCALL_NR] = {
[OCALL_LOAD_DEBUG] = sgx_ocall_load_debug,
[OCALL_EVENTFD] = sgx_ocall_eventfd,
[OCALL_GET_QUOTE] = sgx_ocall_get_quote,
[OCALL_TRIM_EPC_PAGES] = sgx_ocall_trim_epc_pages,
[OCALL_NOTIFY_ACCEPT] = sgx_ocall_notify_accept,
[OCALL_REMOVE_EPC_PAGE] = sgx_ocall_remove_epc_page,
};

#define EDEBUG(code, ms) do {} while (0)
Expand Down
Loading

0 comments on commit 4f2cfa0

Please sign in to comment.