Skip to content

Commit 750e130

Browse files
davidchisnallSeanTAllen
authored andcommitted
Move the LKL host layer to using OE malloc.
I tried this previously, but reverted it because of crashes. The crashes were caused by the fact that LKL allocate memory for the kernel and for `lkl_vprintf` buffers. The former is larger than the OE heap, so fails, resulting in LKL refusing to start. To avoid this, assume that there is only going to be one allocation > 1MiB and that this is the kernel heap. Special case it and provide it via `enclave_mmap`, forward everything else to `oe_malloc`. Other structures should be safe to allocate via `oe_malloc`.
1 parent 7da5353 commit 750e130

File tree

1 file changed

+60
-11
lines changed

1 file changed

+60
-11
lines changed

src/lkl/posix-host.c

+60-11
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "enclave/sgxlkl_t.h"
2424
#include "lkl/iomem.h"
2525
#include "lkl/jmp_buf.h"
26+
#include "openenclave/corelibc/oemalloc.h"
2627
#include "openenclave/internal/print.h"
2728
#include "syscall.h"
2829

@@ -189,7 +190,7 @@ static struct lkl_sem* sem_alloc(int count)
189190
{
190191
struct lkl_sem* sem;
191192

192-
sem = calloc(1, sizeof(*sem));
193+
sem = oe_calloc(1, sizeof(*sem));
193194
if (!sem)
194195
return NULL;
195196

@@ -200,7 +201,7 @@ static struct lkl_sem* sem_alloc(int count)
200201

201202
static void sem_free(struct lkl_sem* sem)
202203
{
203-
free(sem);
204+
oe_free(sem);
204205
}
205206

206207
static void sem_up(struct lkl_sem* sem)
@@ -237,7 +238,7 @@ static void sem_down(struct lkl_sem* sem)
237238

238239
static struct lkl_mutex* mutex_alloc(int recursive)
239240
{
240-
struct lkl_mutex* mutex = calloc(1, sizeof(struct lkl_mutex));
241+
struct lkl_mutex* mutex = oe_calloc(1, sizeof(struct lkl_mutex));
241242

242243
if (!mutex)
243244
return NULL;
@@ -309,7 +310,7 @@ static void mutex_unlock(struct lkl_mutex* mutex)
309310

310311
static void mutex_free(struct lkl_mutex* _mutex)
311312
{
312-
free(_mutex);
313+
oe_free(_mutex);
313314
}
314315

315316
static lkl_thread_t thread_create(void (*fn)(void*), void* arg)
@@ -420,11 +421,11 @@ static int thread_equal(lkl_thread_t a, lkl_thread_t b)
420421
static struct lkl_tls_key* tls_alloc(void (*destructor)(void*))
421422
{
422423
LKL_TRACE("enter (destructor=%p)\n", destructor);
423-
struct lkl_tls_key* ret = malloc(sizeof(struct lkl_tls_key));
424+
struct lkl_tls_key* ret = oe_malloc(sizeof(struct lkl_tls_key));
424425

425426
if (WARN_PTHREAD(lthread_key_create(&ret->key, destructor)))
426427
{
427-
free(ret);
428+
oe_free(ret);
428429
return NULL;
429430
}
430431
return ret;
@@ -434,7 +435,7 @@ static void tls_free(struct lkl_tls_key* key)
434435
{
435436
LKL_TRACE("enter (key=%p)\n", key);
436437
WARN_PTHREAD(lthread_key_delete(key->key));
437-
free(key);
438+
oe_free(key);
438439
}
439440

440441
static int tls_set(struct lkl_tls_key* key, void* data)
@@ -536,7 +537,7 @@ static void* timer_callback(void* _timer)
536537

537538
static void* timer_alloc(void (*fn)(void*), void* arg)
538539
{
539-
sgxlkl_timer* timer = calloc(sizeof(*timer), 1);
540+
sgxlkl_timer* timer = oe_calloc(sizeof(*timer), 1);
540541

541542
if (timer == NULL)
542543
{
@@ -633,14 +634,62 @@ static void timer_free(void* _timer)
633634
mutex_unlock(&timer->mtx);
634635
}
635636

636-
free(_timer);
637+
oe_free(_timer);
637638
}
638639

639640
static long _gettid(void)
640641
{
641642
return (long)lthread_self();
642643
}
643644

645+
/**
646+
* The allocation for kernel memory.
647+
*/
648+
static void *kernel_mem;
649+
/**
650+
* The size of kernel heap area.
651+
*/
652+
static size_t kernel_mem_size;
653+
654+
/**
655+
* Allocate memory for LKL. This is used in precisely two places as we build
656+
* LKL:
657+
*
658+
* 1. Allocating the kernel's memory.
659+
* 2. Allocating buffers for lkl_vprintf to use printing debug messages.
660+
*
661+
* We allocate the former from the `enclave_mmap` space, but smaller buffers
662+
* from the OE heap.
663+
*/
664+
static void *host_malloc(size_t size)
665+
{
666+
// If we're allocating over 1MB, we're probably allocating the kernel heap.
667+
// Pull this out of the enclave mmap area: there isn't enough space in the
668+
// OE heap for it.
669+
if (size > 1024*1024)
670+
{
671+
SGXLKL_ASSERT(kernel_mem == NULL);
672+
kernel_mem = enclave_mmap(0, size, 0, PROT_READ | PROT_WRITE, 0);
673+
kernel_mem_size = size;
674+
return kernel_mem;
675+
}
676+
return oe_malloc(size);
677+
}
678+
679+
/**
680+
* Free memory allocated with `host_malloc`.
681+
*/
682+
static void host_free(void *ptr)
683+
{
684+
if (ptr == kernel_mem)
685+
{
686+
enclave_munmap(kernel_mem, kernel_mem_size);
687+
kernel_mem = 0;
688+
kernel_mem_size = 0;
689+
}
690+
oe_free(ptr);
691+
}
692+
644693
struct lkl_host_operations sgxlkl_host_ops = {
645694
.panic = panic,
646695
.terminate = terminate,
@@ -669,8 +718,8 @@ struct lkl_host_operations sgxlkl_host_ops = {
669718
.timer_set_oneshot = timer_set_oneshot,
670719
.timer_free = timer_free,
671720
.print = print,
672-
.mem_alloc = malloc,
673-
.mem_free = free,
721+
.mem_alloc = host_malloc,
722+
.mem_free = host_free,
674723
.ioremap = lkl_ioremap,
675724
.iomem_access = lkl_iomem_access,
676725
.virtio_devices = lkl_virtio_devs,

0 commit comments

Comments
 (0)