From c7736a2defd718debf0317d6507ebb5177954d75 Mon Sep 17 00:00:00 2001 From: Anand Krishnamoorthi <35780660+anakrish@users.noreply.github.com> Date: Thu, 28 May 2020 11:04:33 -0700 Subject: [PATCH] OpenEnclave PAL: Store enclave heap base/end in inline variables. (#201) PALOpenEnclave object is lazily constructed. I couldn't figure out a straight-forward way to pass the heap bounds to the constructor of PALOpenEnclave object. As an alternative, store the bounds in inline static variables of the PALOpenEnclave class and set them via static setup_initial_range function. - two_alloc_types/alloc1.cc Define oe_allocator_init to forward base, end values to PALOpenEnclave::setup_inital_range - two_alloc_types/main.cc Use oe_allocator_init function to set up heap range. - fixed_region/fixed_region.cc Initialize heap range via call to PALOpenEnclave::setup_inital_range. Signed-off-by: Anand Krishnamoorthi --- src/pal/pal_open_enclave.h | 24 +++++++++++----------- src/test/func/fixed_region/fixed_region.cc | 17 +++------------ src/test/func/two_alloc_types/alloc1.cc | 5 +++++ src/test/func/two_alloc_types/main.cc | 18 ++++------------ 4 files changed, 24 insertions(+), 40 deletions(-) diff --git a/src/pal/pal_open_enclave.h b/src/pal/pal_open_enclave.h index 5e37e04..f8124f5 100644 --- a/src/pal/pal_open_enclave.h +++ b/src/pal/pal_open_enclave.h @@ -3,8 +3,6 @@ #include "ds/address.h" #include "pal_plain.h" #ifdef OPEN_ENCLAVE -extern "C" const void* __oe_get_heap_base(); -extern "C" const void* __oe_get_heap_end(); extern "C" void* oe_memset_s(void* p, size_t p_size, int c, size_t size); extern "C" [[noreturn]] void oe_abort(); @@ -12,9 +10,19 @@ namespace snmalloc { class PALOpenEnclave { - std::atomic oe_base = nullptr; + static inline std::atomic oe_base; + static inline void* oe_end = nullptr; public: + /** + * This will be called by oe_allocator_init to set up enclave heap bounds. + */ + static void setup_initial_range(void* base, void* end) + { + oe_base = base; + oe_end = end; + } + /** * Bitmap of PalFeatures flags indicating the optional features that this * PAL supports. @@ -32,17 +40,9 @@ namespace snmalloc template void* reserve(size_t size) noexcept { - if (oe_base == 0) - { - void* dummy = NULL; - // If this CAS fails then another thread has initialised this. - oe_base.compare_exchange_strong( - dummy, const_cast(__oe_get_heap_base())); - } - void* old_base = oe_base; void* next_base; - auto end = __oe_get_heap_end(); + auto end = oe_end; do { auto new_base = old_base; diff --git a/src/test/func/fixed_region/fixed_region.cc b/src/test/func/fixed_region/fixed_region.cc index 6c96797..4f64700 100644 --- a/src/test/func/fixed_region/fixed_region.cc +++ b/src/test/func/fixed_region/fixed_region.cc @@ -10,18 +10,6 @@ #endif #define assert please_use_SNMALLOC_ASSERT -void* oe_base; -void* oe_end; -extern "C" const void* __oe_get_heap_base() -{ - return oe_base; -} - -extern "C" const void* __oe_get_heap_end() -{ - return oe_end; -} - extern "C" void* oe_memset_s(void* p, size_t p_size, int c, size_t size) { UNUSED(p_size); @@ -43,8 +31,9 @@ int main() // For 1MiB superslabs, SUPERSLAB_BITS + 4 is not big enough for the example. size_t large_class = 28 - SUPERSLAB_BITS; size_t size = 1ULL << (SUPERSLAB_BITS + large_class); - oe_base = mp.reserve(large_class); - oe_end = (uint8_t*)oe_base + size; + void* oe_base = mp.reserve(large_class); + void* oe_end = (uint8_t*)oe_base + size; + PALOpenEnclave::setup_initial_range(oe_base, oe_end); std::cout << "Allocated region " << oe_base << " - " << oe_end << std::endl; auto a = ThreadAlloc::get(); diff --git a/src/test/func/two_alloc_types/alloc1.cc b/src/test/func/two_alloc_types/alloc1.cc index c86dcde..f696600 100644 --- a/src/test/func/two_alloc_types/alloc1.cc +++ b/src/test/func/two_alloc_types/alloc1.cc @@ -9,3 +9,8 @@ // Redefine the namespace, so we can have two versions. #define snmalloc snmalloc_enclave #include "../../../override/malloc.cc" + +extern "C" void oe_allocator_init(void* base, void* end) +{ + snmalloc_enclave::PALOpenEnclave::setup_initial_range(base, end); +} diff --git a/src/test/func/two_alloc_types/main.cc b/src/test/func/two_alloc_types/main.cc index 341f32d..1ef9d1c 100644 --- a/src/test/func/two_alloc_types/main.cc +++ b/src/test/func/two_alloc_types/main.cc @@ -5,18 +5,6 @@ #include #include -void* oe_base; -void* oe_end; -extern "C" const void* __oe_get_heap_base() -{ - return oe_base; -} - -extern "C" const void* __oe_get_heap_end() -{ - return oe_end; -} - extern "C" void* oe_memset_s(void* p, size_t p_size, int c, size_t size) { UNUSED(p_size); @@ -28,6 +16,7 @@ extern "C" void oe_abort() abort(); } +extern "C" void oe_allocator_init(void* base, void* end); extern "C" void* host_malloc(size_t); extern "C" void host_free(void*); @@ -51,8 +40,9 @@ int main() // For 1MiB superslabs, SUPERSLAB_BITS + 2 is not big enough for the example. size_t large_class = 26 - SUPERSLAB_BITS; size_t size = 1ULL << (SUPERSLAB_BITS + large_class); - oe_base = mp.reserve(large_class); - oe_end = (uint8_t*)oe_base + size; + void* oe_base = mp.reserve(large_class); + void* oe_end = (uint8_t*)oe_base + size; + oe_allocator_init(oe_base, oe_end); std::cout << "Allocated region " << oe_base << " - " << oe_end << std::endl; // Call these functions to trigger asserts if the cast-to-self doesn't work.