From f4724c143665319479fd77dc76b5509eb62bb263 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Thu, 2 May 2024 23:21:19 +0200 Subject: [PATCH 01/12] Glue code for using snmalloc in EDP --- .github/workflows/build.yml | 26 ++- .gitmodules | 3 + Cargo.lock | 11 +- Cargo.toml | 1 + snmalloc-edp/CMakeLists.txt | 10 ++ snmalloc-edp/Cargo.toml | 11 ++ snmalloc-edp/build.rs | 5 + snmalloc-edp/snmalloc | 1 + snmalloc-edp/src/lib.rs | 24 +++ snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp | 187 ++++++++++++++++++++ snmalloc-edp/tests/global_alloc.rs | 111 ++++++++++++ 11 files changed, 385 insertions(+), 5 deletions(-) create mode 100644 .gitmodules create mode 100644 snmalloc-edp/CMakeLists.txt create mode 100644 snmalloc-edp/Cargo.toml create mode 100644 snmalloc-edp/build.rs create mode 160000 snmalloc-edp/snmalloc create mode 100644 snmalloc-edp/src/lib.rs create mode 100644 snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp create mode 100644 snmalloc-edp/tests/global_alloc.rs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d9e63fc9..5a54d74b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,7 +16,9 @@ env: CARGO_INCREMENTAL: 0 CARGO_NET_RETRY: 10 CFLAGS_x86_64_fortanix_unknown_sgx: "-isystem/usr/include/x86_64-linux-gnu -mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening" + # CXXFLAGS is set below CC_x86_64_fortanix_unknown_sgx: clang-11 + CXX_x86_64_fortanix_unknown_sgx: clang++-11 jobs: test: @@ -48,7 +50,7 @@ jobs: rustup update - name: Cargo test --all --exclude sgxs-loaders - run: cargo test --verbose --locked --all --exclude sgxs-loaders --exclude async-usercalls && [ "$(echo $(nm -D target/debug/sgx-detect|grep __vdso_sgx_enter_enclave))" = "w __vdso_sgx_enter_enclave" ] + run: true || ( cargo test --verbose --locked --all --exclude sgxs-loaders --exclude async-usercalls --exclude snmalloc-edp && [ "$(echo $(nm -D target/debug/sgx-detect|grep __vdso_sgx_enter_enclave))" = "w __vdso_sgx_enter_enclave" ] ) - name: cargo test -p async-usercalls --target x86_64-fortanix-unknown-sgx --no-run run: cargo +nightly test --verbose --locked -p async-usercalls --target x86_64-fortanix-unknown-sgx --no-run @@ -60,10 +62,10 @@ jobs: run: cargo test --verbose --locked -p dcap-ql --features verify - name: Cargo test -p ias --features mbedtls - run: cargo test --verbose --locked -p ias --features mbedtls + run: true || cargo test --verbose --locked -p ias --features mbedtls - name: Cargo test -p ias --features client,mbedtls - run: cargo test --verbose --locked -p ias --features client,mbedtls + run: true || cargo test --verbose --locked -p ias --features client,mbedtls # uses backtrace, which still requires nightly on SGX - name: Nightly build -p aesm-client --target=x86_64-fortanix-unknown-sgx @@ -96,6 +98,24 @@ jobs: - name: Build em-app, get-certificate for x86_64-fortanix-unknown-sgx run: cargo build --verbose --locked -p em-app -p get-certificate --target=x86_64-fortanix-unknown-sgx + - name: Build snmalloc-edp + run: | + git submodule update --init --recursive + detect_cxx_include_path() { + for path in $(clang++-12 -print-search-dirs|sed -n 's/^libraries:\s*=//p'|tr : ' '); do + num_component="$(basename "$path")" + if [[ "$num_component" =~ ^[0-9]+(\.[0-9]+)*$ ]]; then + if [[ "$(basename "$(dirname "$path")")" == 'x86_64-linux-gnu' ]]; then + echo $num_component + return + fi + fi + done + exit 1 + } + export CXXFLAGS_x86_64_fortanix_unknown_sgx="-cxx-isystem/usr/include/c++/$(detect_cxx_include_path) -cxx-isystem/usr/include/x86_64-linux-gnu/c++/$(detect_cxx_include_path) $CFLAGS_x86_64_fortanix_unknown_sgx" + cargo test --no-run --verbose --locked -p snmalloc-edp --target=x86_64-fortanix-unknown-sgx + - name: Generate API docs run: ./doc/generate-api-docs.sh diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..905063cd --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "snmalloc-edp/snmalloc"] + path = snmalloc-edp/snmalloc + url = https://github.com/microsoft/snmalloc diff --git a/Cargo.lock b/Cargo.lock index e33c816c..369ad6e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -420,9 +420,9 @@ dependencies = [ [[package]] name = "cmake" -version = "0.1.44" +version = "0.1.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e56268c17a6248366d66d4a47a3381369d068cce8409bb1716ed77ea32163bb" +checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" dependencies = [ "cc", ] @@ -3366,6 +3366,13 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" +[[package]] +name = "snmalloc-edp" +version = "0.1.0" +dependencies = [ + "cmake", +] + [[package]] name = "socket2" version = "0.4.2" diff --git a/Cargo.toml b/Cargo.toml index 069a108c..0d1e379f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,7 @@ members = [ "intel-sgx/sgxs", "ipc-queue", "rs-libc", + "snmalloc-edp", ] exclude = [ "examples/backtrace_panic", diff --git a/snmalloc-edp/CMakeLists.txt b/snmalloc-edp/CMakeLists.txt new file mode 100644 index 00000000..b87eee49 --- /dev/null +++ b/snmalloc-edp/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.14) +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) +project(snmalloc-edp CXX) +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED True) +set(SNMALLOC_HEADER_ONLY_LIBRARY ON) +add_subdirectory(snmalloc EXCLUDE_FROM_ALL) +add_library(snmalloc-edp src/rust-sgx-snmalloc-shim.cpp) +target_link_libraries(snmalloc-edp PRIVATE snmalloc_lib) +target_compile_options(snmalloc-edp PRIVATE -nostdlib -ffreestanding -fno-exceptions -mrdrnd -fPIC) diff --git a/snmalloc-edp/Cargo.toml b/snmalloc-edp/Cargo.toml new file mode 100644 index 00000000..053d5adb --- /dev/null +++ b/snmalloc-edp/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "snmalloc-edp" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +build = "build.rs" + +[build-dependencies] +cmake = "0.1.50" diff --git a/snmalloc-edp/build.rs b/snmalloc-edp/build.rs new file mode 100644 index 00000000..2aeacf02 --- /dev/null +++ b/snmalloc-edp/build.rs @@ -0,0 +1,5 @@ +fn main() { + let mut dst = cmake::build("."); + dst.push("build"); + println!("cargo:rustc-link-search=native={}", dst.display()); +} diff --git a/snmalloc-edp/snmalloc b/snmalloc-edp/snmalloc new file mode 160000 index 00000000..dc126888 --- /dev/null +++ b/snmalloc-edp/snmalloc @@ -0,0 +1 @@ +Subproject commit dc1268886a5d49d38a54e5d1402b5924a71fee0b diff --git a/snmalloc-edp/src/lib.rs b/snmalloc-edp/src/lib.rs new file mode 100644 index 00000000..4840519f --- /dev/null +++ b/snmalloc-edp/src/lib.rs @@ -0,0 +1,24 @@ +#![no_std] + +use core::ffi::c_void; + +#[repr(C)] +pub struct Alloc { + _data: [u8; 0], + _marker: + core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>, +} + +#[link(name = "snmalloc-edp", kind = "static")] +extern { + pub fn sn_global_init(heap_start_address: *mut c_void, heap_end_address: *mut c_void); + pub fn sn_thread_init(allocator: *mut Alloc); + pub fn sn_thread_cleanup(allocator: *mut Alloc); + pub static sn_alloc_size: usize; + pub static sn_alloc_align: usize; + + pub fn sn_rust_alloc(alignment: usize, size: usize) -> *mut u8; + pub fn sn_rust_alloc_zeroed(alignment: usize, size: usize) -> *mut u8; + pub fn sn_rust_dealloc(ptr: *mut u8, alignment: usize, size: usize); + pub fn sn_rust_realloc(ptr: *mut u8, alignment: usize, old_size: usize, new_size: usize) -> *mut u8; +} diff --git a/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp b/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp new file mode 100644 index 00000000..31324fc0 --- /dev/null +++ b/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp @@ -0,0 +1,187 @@ +// Copyright (c) Microsoft Corporation. +// Copyright (c) Open Enclave SDK contributors. +// Copyright (c) 2020 SchrodingerZhu +// Copyright (c) Fortanix, Inc. +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE + +#include +#include + +/***************************************************/ +/*** Imported symbols needed by snmalloc SGX PAL ***/ +/***************************************************/ + +// from entry.S +extern "C" size_t get_tcs_addr(); + +// from Rust std +extern "C" void __rust_print_err(const char *m, size_t s); +extern "C" [[noreturn]] void __rust_abort(); + +/*******************************************************/ +/*** Standard C functions needed by snmalloc SGX PAL ***/ +/*******************************************************/ + +// definition needs to match GNU header +extern "C" [[noreturn]] void abort() __THROW { + __rust_abort(); +} + +// definition needs to match GNU header +extern "C" inline int * __attribute_const__ __errno_location (void) __THROW { + static int errno; + return &errno; +} + +/***********************************/ +/*** snmalloc SGX PAL definition ***/ +/***********************************/ + +#define SNMALLOC_PROVIDE_OWN_CONFIG +#define SNMALLOC_SGX +#define SNMALLOC_USE_SMALL_CHUNKS +#define SNMALLOC_MEMORY_PROVIDER PALEdpSgx +#define OPEN_ENCLAVE +// needed for openenclave header: +#define OE_OK 0 + +#include "../snmalloc/src/snmalloc/pal/pal_noalloc.h" + +namespace snmalloc { +void register_clean_up() { + // TODO: not sure what this is supposed to do + abort(); +} + +class EdpErrorHandler { + public: + static void print_stack_trace() {} + + [[noreturn]] static void error(const char *const str) { + __rust_print_err(str, strlen(str)); + abort(); + } + static constexpr size_t address_bits = Aal::address_bits; + static constexpr size_t page_size = Aal::smallest_page_size; +}; + +using EdpBasePAL = PALNoAlloc; + +class PALEdpSgx : public EdpBasePAL { + public: + using ThreadIdentity = size_t; + static constexpr uint64_t pal_features = EdpBasePAL::pal_features | Entropy; + + template + static void zero(void *p, size_t size) noexcept { + memset(p, 0, size); + } + + static inline uint64_t get_entropy64() { + long long unsigned int result = 0; + while (_rdrand64_step(&result) != 1) + ; + return result; + } + + static inline ThreadIdentity get_tid() noexcept { + return (size_t)get_tcs_addr(); + } +}; +} // namespace snmalloc + +/**************************************/ +/*** Instantiation of the allocator ***/ +/**************************************/ + +#include "../snmalloc/src/snmalloc/backend/fixedglobalconfig.h" +#include "../snmalloc/src/snmalloc/snmalloc_core.h" + +using namespace snmalloc; + +using Globals = FixedRangeConfig; +using Alloc = LocalAllocator; + +/// Do global initialization for snmalloc. Should be called exactly once prior +/// to any other snmalloc function calls. +// TODO: this function shouldn't need the addresses passed in, these can be +// obtained from the HEAP_* symbols +extern "C" void sn_global_init(void *heap_start_address, + void *heap_end_address) { + size_t _max_heap_size = + static_cast(static_cast(heap_end_address) - + static_cast(heap_start_address)); + + Globals::init(nullptr, heap_start_address, _max_heap_size); +} + +/// Construct a thread-local allocator object in place +extern "C" void sn_thread_init(Alloc* allocator) { + new(allocator) Alloc(); + allocator->init(); +} + +/// Destruct a thread-local allocator object in place +extern "C" void sn_thread_cleanup(Alloc* allocator) { + allocator->teardown(); + allocator->~Alloc(); +} + +extern "C" size_t sn_alloc_size = sizeof(Alloc); +extern "C" size_t sn_alloc_align = alignof(Alloc); + +/// Return a pointer to a thread-local allocator object of size +/// `sn_alloc_size` and alignment `sn_alloc_align`. +extern "C" Alloc* __rust_get_thread_allocator(); + +/******************************************************/ +/*** Rust-compatible shims for the global allocator ***/ +/******************************************************/ + +extern "C" void *sn_rust_alloc(size_t alignment, size_t size) { + return __rust_get_thread_allocator()->alloc(aligned_size(alignment, size)); +} + +extern "C" void *sn_rust_alloc_zeroed(size_t alignment, size_t size) { + return __rust_get_thread_allocator()->alloc( + aligned_size(alignment, size)); +} + +extern "C" void sn_rust_dealloc(void *ptr, size_t alignment, size_t size) { + __rust_get_thread_allocator()->dealloc(ptr, aligned_size(alignment, size)); +} + +extern "C" void *sn_rust_realloc(void *ptr, size_t alignment, size_t old_size, + size_t new_size) { + size_t aligned_old_size = aligned_size(alignment, old_size), + aligned_new_size = aligned_size(alignment, new_size); + if (size_to_sizeclass_full(aligned_old_size).raw() == + size_to_sizeclass_full(aligned_new_size).raw()) + return ptr; + Alloc* allocator = __rust_get_thread_allocator(); + void *p = allocator->alloc(aligned_new_size); + if (p) { + std::memcpy(p, ptr, old_size < new_size ? old_size : new_size); + allocator->dealloc(ptr, aligned_old_size); + } + return p; +} diff --git a/snmalloc-edp/tests/global_alloc.rs b/snmalloc-edp/tests/global_alloc.rs new file mode 100644 index 00000000..f09e5a7b --- /dev/null +++ b/snmalloc-edp/tests/global_alloc.rs @@ -0,0 +1,111 @@ +use std::{alloc::{self, GlobalAlloc}, cell::Cell, ptr}; + +use snmalloc_edp::*; + +thread_local! { + static THREAD_ALLOC: Cell<*mut Alloc> = const { Cell::new(ptr::null_mut()) }; +} + +#[no_mangle] +pub fn __rust_get_thread_allocator() -> *mut Alloc { + THREAD_ALLOC.get() +} + +struct System; + +unsafe impl alloc::GlobalAlloc for System { + #[inline] + unsafe fn alloc(&self, layout: alloc::Layout) -> *mut u8 { + // SAFETY: the caller must uphold the safety contract for `malloc` + sn_rust_alloc(layout.align(), layout.size()) + } + + #[inline] + unsafe fn alloc_zeroed(&self, layout: alloc::Layout) -> *mut u8 { + // SAFETY: the caller must uphold the safety contract for `malloc` + sn_rust_alloc_zeroed(layout.align(), layout.size()) + } + + #[inline] + unsafe fn dealloc(&self, ptr: *mut u8, layout: alloc::Layout) { + // SAFETY: the caller must uphold the safety contract for `malloc` + sn_rust_dealloc(ptr, layout.align(), layout.size()) + } + + #[inline] + unsafe fn realloc(&self, ptr: *mut u8, layout: alloc::Layout, new_size: usize) -> *mut u8 { + // SAFETY: the caller must uphold the safety contract for `malloc` + sn_rust_realloc(ptr, layout.align(), layout.size(), new_size) + } +} + +// SAFETY: this should only be called once per thread, and the global +// allocator shouldn't be used outside of this function +unsafe fn with_thread_allocator R, R>(f: F) -> R { + unsafe { + let layout = alloc::Layout::from_size_align(sn_alloc_size, sn_alloc_align).unwrap(); + // TODO: bootstrap the thread-local allocator allocation a different way + let allocator = alloc::alloc(layout) as *mut Alloc; + sn_thread_init(allocator); + THREAD_ALLOC.set(allocator); + + let r = f(); + + THREAD_ALLOC.set(ptr::null_mut()); + sn_thread_cleanup(allocator); + alloc::dealloc(allocator as _, layout); + + r + } +} + +#[test] +fn test() { + unsafe { + #[allow(dead_code)] + #[derive(Copy, Clone)] + #[repr(align(0x1000))] + struct Page([u8; 0x1000]); + + // allocate a dummy heap + let heap = (*Box::into_raw(vec![Page([0; 4096]); 100].into_boxed_slice())).as_mut_ptr_range(); + + sn_global_init(heap.start as _, heap.end as _); + } + + type AllocTestType = [u64; 20]; + + let barrier = std::sync::Barrier::new(2); + + std::thread::scope(|s| { + let (tx, rx) = std::sync::mpsc::sync_channel(0); + let barrier = &barrier; + s.spawn(move || { + unsafe { + with_thread_allocator(|| { + let p1 = System.alloc(alloc::Layout::new::()); + barrier.wait(); + let p2 = System.alloc(alloc::Layout::new::()); + tx.send((p1 as usize, p2 as usize)).unwrap(); + }) + }; + }); + + let (p1, p2) = unsafe { + with_thread_allocator(|| { + let p1 = System.alloc(alloc::Layout::new::()); + barrier.wait(); + let p2 = System.alloc(alloc::Layout::new::()); + (p1 as usize, p2 as usize) + }) + }; + let (p3, p4) = rx.recv().unwrap(); + assert_ne!(p1, p2); + assert_ne!(p1, p3); + assert_ne!(p1, p4); + assert_ne!(p2, p3); + assert_ne!(p2, p4); + assert_ne!(p3, p4); + }) + +} From d81d2d1223f049858c1fd7f5d6284747e70a7794 Mon Sep 17 00:00:00 2001 From: Nirjhar Roy Date: Tue, 7 May 2024 06:15:26 +0000 Subject: [PATCH 02/12] Putting a limit to random number generation retries --- snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp b/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp index 31324fc0..479c165a 100644 --- a/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp +++ b/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp @@ -11,10 +11,10 @@ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -87,7 +87,8 @@ class EdpErrorHandler { using EdpBasePAL = PALNoAlloc; class PALEdpSgx : public EdpBasePAL { - public: + public: + const static size_t RAND_NUM_GEN_MAX_RETRIES = 64; using ThreadIdentity = size_t; static constexpr uint64_t pal_features = EdpBasePAL::pal_features | Entropy; @@ -97,9 +98,11 @@ class PALEdpSgx : public EdpBasePAL { } static inline uint64_t get_entropy64() { + long long unsigned int retry_count = 0; long long unsigned int result = 0; - while (_rdrand64_step(&result) != 1) - ; + while (_rdrand64_step(&result) != 1 && retry_count < RAND_NUM_GEN_MAX_RETRIES) { + retry_count++; + } return result; } From 313d443c939510c3cac307083b1c06e3924705d0 Mon Sep 17 00:00:00 2001 From: Nirjhar Roy Date: Tue, 7 May 2024 09:38:12 +0000 Subject: [PATCH 03/12] Removing the formal parameters in sn_global_init() function --- snmalloc-edp/src/lib.rs | 4 +--- snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp | 14 +++++++------- snmalloc-edp/tests/global_alloc.rs | 4 ++-- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/snmalloc-edp/src/lib.rs b/snmalloc-edp/src/lib.rs index 4840519f..c39f1e04 100644 --- a/snmalloc-edp/src/lib.rs +++ b/snmalloc-edp/src/lib.rs @@ -1,7 +1,5 @@ #![no_std] -use core::ffi::c_void; - #[repr(C)] pub struct Alloc { _data: [u8; 0], @@ -11,7 +9,7 @@ pub struct Alloc { #[link(name = "snmalloc-edp", kind = "static")] extern { - pub fn sn_global_init(heap_start_address: *mut c_void, heap_end_address: *mut c_void); + pub fn sn_global_init(); pub fn sn_thread_init(allocator: *mut Alloc); pub fn sn_thread_cleanup(allocator: *mut Alloc); pub static sn_alloc_size: usize; diff --git a/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp b/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp index 479c165a..eaff2785 100644 --- a/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp +++ b/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp @@ -52,6 +52,11 @@ extern "C" inline int * __attribute_const__ __errno_location (void) __THROW { return &errno; } +extern "C" { + static size_t HEAP_BASE; + static size_t HEAP_SIZE; +}; + /***********************************/ /*** snmalloc SGX PAL definition ***/ /***********************************/ @@ -128,13 +133,8 @@ using Alloc = LocalAllocator; /// to any other snmalloc function calls. // TODO: this function shouldn't need the addresses passed in, these can be // obtained from the HEAP_* symbols -extern "C" void sn_global_init(void *heap_start_address, - void *heap_end_address) { - size_t _max_heap_size = - static_cast(static_cast(heap_end_address) - - static_cast(heap_start_address)); - - Globals::init(nullptr, heap_start_address, _max_heap_size); +extern "C" void sn_global_init() { + Globals::init(nullptr, (void *)HEAP_BASE, HEAP_SIZE); } /// Construct a thread-local allocator object in place diff --git a/snmalloc-edp/tests/global_alloc.rs b/snmalloc-edp/tests/global_alloc.rs index f09e5a7b..39ee4c5f 100644 --- a/snmalloc-edp/tests/global_alloc.rs +++ b/snmalloc-edp/tests/global_alloc.rs @@ -68,9 +68,9 @@ fn test() { struct Page([u8; 0x1000]); // allocate a dummy heap - let heap = (*Box::into_raw(vec![Page([0; 4096]); 100].into_boxed_slice())).as_mut_ptr_range(); + let _heap = (*Box::into_raw(vec![Page([0; 4096]); 100].into_boxed_slice())).as_mut_ptr_range(); - sn_global_init(heap.start as _, heap.end as _); + sn_global_init(); } type AllocTestType = [u64; 20]; From 89982368047209f4b71205cb654f8bad68f401f1 Mon Sep 17 00:00:00 2001 From: Nirjhar Roy Date: Tue, 7 May 2024 11:28:58 +0000 Subject: [PATCH 04/12] minor edits --- snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp b/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp index eaff2785..349c3371 100644 --- a/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp +++ b/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp @@ -103,12 +103,13 @@ class PALEdpSgx : public EdpBasePAL { } static inline uint64_t get_entropy64() { - long long unsigned int retry_count = 0; - long long unsigned int result = 0; - while (_rdrand64_step(&result) != 1 && retry_count < RAND_NUM_GEN_MAX_RETRIES) { - retry_count++; + for (size_t retry_count = 0; retry_count < RAND_NUM_GEN_MAX_RETRIES; retry_count++) { + long long unsigned int result; + if (_rdrand64_step(&result) == 1) { + return result; + } } - return result; + EdpErrorHandler::error("no entropy available"); } static inline ThreadIdentity get_tid() noexcept { From e84e65c6796cea122e3ed43b76b64525ed102751 Mon Sep 17 00:00:00 2001 From: Nirjhar Roy Date: Wed, 8 May 2024 12:50:01 +0000 Subject: [PATCH 05/12] fixing build issues related to Unverified struct --- .github/workflows/build.yml | 6 +++--- intel-sgx/ias/src/api.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5a54d74b..1d0c6656 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -50,7 +50,7 @@ jobs: rustup update - name: Cargo test --all --exclude sgxs-loaders - run: true || ( cargo test --verbose --locked --all --exclude sgxs-loaders --exclude async-usercalls --exclude snmalloc-edp && [ "$(echo $(nm -D target/debug/sgx-detect|grep __vdso_sgx_enter_enclave))" = "w __vdso_sgx_enter_enclave" ] ) + run: cargo test --verbose --locked --all --exclude sgxs-loaders --exclude async-usercalls --exclude snmalloc-edp && [ "$(echo $(nm -D target/debug/sgx-detect|grep __vdso_sgx_enter_enclave))" = "w __vdso_sgx_enter_enclave" ] - name: cargo test -p async-usercalls --target x86_64-fortanix-unknown-sgx --no-run run: cargo +nightly test --verbose --locked -p async-usercalls --target x86_64-fortanix-unknown-sgx --no-run @@ -62,10 +62,10 @@ jobs: run: cargo test --verbose --locked -p dcap-ql --features verify - name: Cargo test -p ias --features mbedtls - run: true || cargo test --verbose --locked -p ias --features mbedtls + run: cargo test --verbose --locked -p ias --features mbedtls - name: Cargo test -p ias --features client,mbedtls - run: true || cargo test --verbose --locked -p ias --features client,mbedtls + run: cargo test --verbose --locked -p ias --features client,mbedtls # uses backtrace, which still requires nightly on SGX - name: Nightly build -p aesm-client --target=x86_64-fortanix-unknown-sgx diff --git a/intel-sgx/ias/src/api.rs b/intel-sgx/ias/src/api.rs index b1efc72b..debbd402 100644 --- a/intel-sgx/ias/src/api.rs +++ b/intel-sgx/ias/src/api.rs @@ -193,7 +193,7 @@ pub struct VerifiedSig {} impl VerificationType for VerifiedSig {} #[derive(Clone, Debug, Eq, PartialEq, Hash)] -pub(crate) struct Unverified {} +pub enum Unverified {} impl VerificationType for Unverified {} trait SafeToDeserializeInto {} From 1461ce5bd731d1b84091d4c2ee5872f62224d9ed Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 14 May 2024 12:43:33 +0200 Subject: [PATCH 06/12] Make available compile-time constants for C Alloc type --- Cargo.lock | 10 ++++- snmalloc-edp/Cargo.toml | 2 + snmalloc-edp/build.rs | 59 ++++++++++++++++++++++++++++++ snmalloc-edp/src/lib.rs | 9 +---- snmalloc-edp/tests/global_alloc.rs | 11 ++---- 5 files changed, 75 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 369ad6e7..c4c3d4bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -724,7 +724,7 @@ dependencies = [ "anyhow", "cargo_toml", "clap", - "elf", + "elf 0.0.10", "env_logger 0.9.0", "log 0.4.21", "nitro-cli", @@ -785,6 +785,12 @@ dependencies = [ "byteorder 0.5.3", ] +[[package]] +name = "elf" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b" + [[package]] name = "em-app" version = "0.4.0" @@ -3370,7 +3376,9 @@ checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" name = "snmalloc-edp" version = "0.1.0" dependencies = [ + "cc", "cmake", + "elf 0.7.4", ] [[package]] diff --git a/snmalloc-edp/Cargo.toml b/snmalloc-edp/Cargo.toml index 053d5adb..05bb72df 100644 --- a/snmalloc-edp/Cargo.toml +++ b/snmalloc-edp/Cargo.toml @@ -8,4 +8,6 @@ edition = "2021" build = "build.rs" [build-dependencies] +cc = "1.0.86" cmake = "0.1.50" +elf = "0.7" diff --git a/snmalloc-edp/build.rs b/snmalloc-edp/build.rs index 2aeacf02..cdbceb36 100644 --- a/snmalloc-edp/build.rs +++ b/snmalloc-edp/build.rs @@ -1,5 +1,64 @@ +use std::fs::{DirEntry, File}; +use std::path::{Path, PathBuf}; + +fn files_in_dir(p: &Path) -> impl Iterator { + p.read_dir().unwrap().map(|e| e.unwrap()).filter(|e| e.file_type().unwrap().is_file()) +} + fn main() { + let out_dir = PathBuf::from(std::env::var_os("OUT_DIR").unwrap()); + + // # Use CMake to build the shim let mut dst = cmake::build("."); dst.push("build"); println!("cargo:rustc-link-search=native={}", dst.display()); + + // # Extract the static library archive into a temporary directory + let mut objs = out_dir.clone(); + objs.push("objs"); + std::fs::create_dir_all(&objs).unwrap(); + // clear existing files in the temp dir + for file in files_in_dir(&objs) { + std::fs::remove_file(file.path()).unwrap(); + } + + dst.push("libsnmalloc-edp.a"); + + let mut ar = cc::Build::new().get_archiver(); + ar.args(&["x", "--output"]); + ar.arg(&objs); + ar.arg(dst); + assert!(ar.status().unwrap().success()); + + // # Read the symbols from the shim ELF object + let f = files_in_dir(&objs).next().unwrap(); + let mut elf = elf::ElfStream::::open_stream(File::open(f.path()).unwrap()).unwrap(); + let (symtab, strtab) = elf.symbol_table().unwrap().unwrap(); + let mut sn_alloc_size = None; + let mut sn_alloc_align = None; + for sym in symtab { + match strtab.get(sym.st_name as _).unwrap() { + "sn_alloc_size" => assert!(sn_alloc_size.replace(sym).is_none()), + "sn_alloc_align" => assert!(sn_alloc_align.replace(sym).is_none()), + _ => {} + } + } + let sn_alloc_size = sn_alloc_size.expect("sn_alloc_size"); + let sn_alloc_align = sn_alloc_align.expect("sn_alloc_align"); + + let mut get_u64_at_symbol = |sym: elf::symbol::Symbol| { + assert_eq!(sym.st_size, 8); + let (data, _) = elf.section_data(&elf.section_headers()[sym.st_shndx as usize].clone()).unwrap(); + let data: &[u8; 8] = data.split_at(8).0.try_into().unwrap(); + u64::from_le_bytes(*data) + }; + + let sn_alloc_size = get_u64_at_symbol(sn_alloc_size); + let sn_alloc_align = get_u64_at_symbol(sn_alloc_align); + + // # Write the type + let contents = format!("#[repr(align({}), C)] pub struct Alloc {{ _0: [u8; {}] }}", sn_alloc_align, sn_alloc_size); + let mut alloc_type_rs = out_dir.clone(); + alloc_type_rs.push("alloc-type.rs"); + std::fs::write(alloc_type_rs, contents).unwrap(); } diff --git a/snmalloc-edp/src/lib.rs b/snmalloc-edp/src/lib.rs index c39f1e04..912a49cc 100644 --- a/snmalloc-edp/src/lib.rs +++ b/snmalloc-edp/src/lib.rs @@ -1,19 +1,12 @@ #![no_std] -#[repr(C)] -pub struct Alloc { - _data: [u8; 0], - _marker: - core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>, -} +include!(concat!(env!("OUT_DIR"), "/alloc-type.rs")); #[link(name = "snmalloc-edp", kind = "static")] extern { pub fn sn_global_init(); pub fn sn_thread_init(allocator: *mut Alloc); pub fn sn_thread_cleanup(allocator: *mut Alloc); - pub static sn_alloc_size: usize; - pub static sn_alloc_align: usize; pub fn sn_rust_alloc(alignment: usize, size: usize) -> *mut u8; pub fn sn_rust_alloc_zeroed(alignment: usize, size: usize) -> *mut u8; diff --git a/snmalloc-edp/tests/global_alloc.rs b/snmalloc-edp/tests/global_alloc.rs index 39ee4c5f..03830442 100644 --- a/snmalloc-edp/tests/global_alloc.rs +++ b/snmalloc-edp/tests/global_alloc.rs @@ -43,17 +43,14 @@ unsafe impl alloc::GlobalAlloc for System { // allocator shouldn't be used outside of this function unsafe fn with_thread_allocator R, R>(f: F) -> R { unsafe { - let layout = alloc::Layout::from_size_align(sn_alloc_size, sn_alloc_align).unwrap(); - // TODO: bootstrap the thread-local allocator allocation a different way - let allocator = alloc::alloc(layout) as *mut Alloc; - sn_thread_init(allocator); - THREAD_ALLOC.set(allocator); + let mut allocator = std::mem::MaybeUninit::::uninit(); + sn_thread_init(allocator.as_mut_ptr()); + THREAD_ALLOC.set(allocator.as_mut_ptr()); let r = f(); THREAD_ALLOC.set(ptr::null_mut()); - sn_thread_cleanup(allocator); - alloc::dealloc(allocator as _, layout); + sn_thread_cleanup(allocator.as_mut_ptr()); r } From 8478e0c3b5761103661717b715f106a28a2105bc Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 14 May 2024 13:05:54 +0200 Subject: [PATCH 07/12] Add rerun-if-changed commands for C sources --- snmalloc-edp/build.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/snmalloc-edp/build.rs b/snmalloc-edp/build.rs index cdbceb36..6e891726 100644 --- a/snmalloc-edp/build.rs +++ b/snmalloc-edp/build.rs @@ -13,6 +13,10 @@ fn main() { dst.push("build"); println!("cargo:rustc-link-search=native={}", dst.display()); + // ideally, the cmake crate would have a way to output this + println!("cargo:rerun-if-changed=CMakeLists.txt"); + println!("cargo:rerun-if-changed=src/rust-sgx-snmalloc-shim.cpp"); + // # Extract the static library archive into a temporary directory let mut objs = out_dir.clone(); objs.push("objs"); From ac0c2a16324f2a74b5c2d9b6dbf204fb3c89b0f7 Mon Sep 17 00:00:00 2001 From: aditijannu Date: Tue, 14 May 2024 15:40:56 +0200 Subject: [PATCH 08/12] Update Cargo to include rust std as a dependency --- snmalloc-edp/Cargo.toml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/snmalloc-edp/Cargo.toml b/snmalloc-edp/Cargo.toml index 05bb72df..a5ef6f8a 100644 --- a/snmalloc-edp/Cargo.toml +++ b/snmalloc-edp/Cargo.toml @@ -11,3 +11,11 @@ build = "build.rs" cc = "1.0.86" cmake = "0.1.50" elf = "0.7" + +[dependencies] +core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" } +compiler_builtins = { version = "0.1.0", optional = true } + +[features] +docs = [] +rustc-dep-of-std = ["core", "compiler_builtins/rustc-dep-of-std"] From a79791b765dbd330d8b2c754894a8a0f735e8056 Mon Sep 17 00:00:00 2001 From: aditijannu Date: Thu, 16 May 2024 10:58:42 +0200 Subject: [PATCH 09/12] Use heap_base and heap_size fn rather than the variable to obtain relocated address --- snmalloc-edp/src/lib.rs | 2 +- snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/snmalloc-edp/src/lib.rs b/snmalloc-edp/src/lib.rs index 912a49cc..6669e653 100644 --- a/snmalloc-edp/src/lib.rs +++ b/snmalloc-edp/src/lib.rs @@ -4,7 +4,7 @@ include!(concat!(env!("OUT_DIR"), "/alloc-type.rs")); #[link(name = "snmalloc-edp", kind = "static")] extern { - pub fn sn_global_init(); + pub fn sn_global_init(heap_base: *const u8, heap_size: usize); pub fn sn_thread_init(allocator: *mut Alloc); pub fn sn_thread_cleanup(allocator: *mut Alloc); diff --git a/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp b/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp index 349c3371..b07f87dc 100644 --- a/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp +++ b/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp @@ -52,11 +52,6 @@ extern "C" inline int * __attribute_const__ __errno_location (void) __THROW { return &errno; } -extern "C" { - static size_t HEAP_BASE; - static size_t HEAP_SIZE; -}; - /***********************************/ /*** snmalloc SGX PAL definition ***/ /***********************************/ @@ -134,8 +129,8 @@ using Alloc = LocalAllocator; /// to any other snmalloc function calls. // TODO: this function shouldn't need the addresses passed in, these can be // obtained from the HEAP_* symbols -extern "C" void sn_global_init() { - Globals::init(nullptr, (void *)HEAP_BASE, HEAP_SIZE); +extern "C" void sn_global_init(void* heap_base, size_t heap_size) { + Globals::init(nullptr, heap_base, heap_size); } /// Construct a thread-local allocator object in place From 6fc0b33a8c0fe2a36e9511b22c5cbc2df57df19e Mon Sep 17 00:00:00 2001 From: aditijannu Date: Tue, 21 May 2024 15:49:22 +0200 Subject: [PATCH 10/12] Remove OPEN_ENCLAVE flag --- snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp b/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp index b07f87dc..06a59f76 100644 --- a/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp +++ b/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp @@ -60,9 +60,6 @@ extern "C" inline int * __attribute_const__ __errno_location (void) __THROW { #define SNMALLOC_SGX #define SNMALLOC_USE_SMALL_CHUNKS #define SNMALLOC_MEMORY_PROVIDER PALEdpSgx -#define OPEN_ENCLAVE -// needed for openenclave header: -#define OE_OK 0 #include "../snmalloc/src/snmalloc/pal/pal_noalloc.h" @@ -127,8 +124,6 @@ using Alloc = LocalAllocator; /// Do global initialization for snmalloc. Should be called exactly once prior /// to any other snmalloc function calls. -// TODO: this function shouldn't need the addresses passed in, these can be -// obtained from the HEAP_* symbols extern "C" void sn_global_init(void* heap_base, size_t heap_size) { Globals::init(nullptr, heap_base, heap_size); } From 93a9e46356827e86059f069f0d8d4607f259d459 Mon Sep 17 00:00:00 2001 From: aditijannu Date: Tue, 4 Jun 2024 15:58:14 +0200 Subject: [PATCH 11/12] fix CI --- snmalloc-edp/tests/global_alloc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snmalloc-edp/tests/global_alloc.rs b/snmalloc-edp/tests/global_alloc.rs index 03830442..dfdeeafe 100644 --- a/snmalloc-edp/tests/global_alloc.rs +++ b/snmalloc-edp/tests/global_alloc.rs @@ -65,9 +65,9 @@ fn test() { struct Page([u8; 0x1000]); // allocate a dummy heap - let _heap = (*Box::into_raw(vec![Page([0; 4096]); 100].into_boxed_slice())).as_mut_ptr_range(); + let heap = (*Box::into_raw(vec![Page([0; 4096]); 100].into_boxed_slice())).as_mut_ptr_range(); - sn_global_init(); + sn_global_init(heap.start as _, heap.end as _); } type AllocTestType = [u64; 20]; From 9cf7ed2ec6fb39460c1cd8d59b8d5c7226ed1bbe Mon Sep 17 00:00:00 2001 From: aditijannu Date: Tue, 25 Jun 2024 16:37:44 +0200 Subject: [PATCH 12/12] Review comments addressed and cleanup --- snmalloc-edp/build.rs | 21 ++++++++------- snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp | 8 +++--- snmalloc-edp/tests/global_alloc.rs | 30 ++++++++++++++++----- 3 files changed, 39 insertions(+), 20 deletions(-) diff --git a/snmalloc-edp/build.rs b/snmalloc-edp/build.rs index 6e891726..cf49d451 100644 --- a/snmalloc-edp/build.rs +++ b/snmalloc-edp/build.rs @@ -1,3 +1,5 @@ +use elf::ElfStream; +use elf::endian::LittleEndian; use std::fs::{DirEntry, File}; use std::path::{Path, PathBuf}; @@ -35,6 +37,7 @@ fn main() { assert!(ar.status().unwrap().success()); // # Read the symbols from the shim ELF object + assert_eq!(files_in_dir(&objs).count(), 1); let f = files_in_dir(&objs).next().unwrap(); let mut elf = elf::ElfStream::::open_stream(File::open(f.path()).unwrap()).unwrap(); let (symtab, strtab) = elf.symbol_table().unwrap().unwrap(); @@ -50,15 +53,8 @@ fn main() { let sn_alloc_size = sn_alloc_size.expect("sn_alloc_size"); let sn_alloc_align = sn_alloc_align.expect("sn_alloc_align"); - let mut get_u64_at_symbol = |sym: elf::symbol::Symbol| { - assert_eq!(sym.st_size, 8); - let (data, _) = elf.section_data(&elf.section_headers()[sym.st_shndx as usize].clone()).unwrap(); - let data: &[u8; 8] = data.split_at(8).0.try_into().unwrap(); - u64::from_le_bytes(*data) - }; - - let sn_alloc_size = get_u64_at_symbol(sn_alloc_size); - let sn_alloc_align = get_u64_at_symbol(sn_alloc_align); + let sn_alloc_size = get_u64_at_symbol(sn_alloc_size, &mut elf); + let sn_alloc_align = get_u64_at_symbol(sn_alloc_align, &mut elf); // # Write the type let contents = format!("#[repr(align({}), C)] pub struct Alloc {{ _0: [u8; {}] }}", sn_alloc_align, sn_alloc_size); @@ -66,3 +62,10 @@ fn main() { alloc_type_rs.push("alloc-type.rs"); std::fs::write(alloc_type_rs, contents).unwrap(); } + +fn get_u64_at_symbol(sym: elf::symbol::Symbol, elf: &mut ElfStream) -> u64 { + assert_eq!(sym.st_size, 8); + let (data, _) = elf.section_data(&elf.section_headers()[sym.st_shndx as usize].clone()).unwrap(); + let data: &[u8; 8] = data.split_at(8).0.try_into().unwrap(); + u64::from_le_bytes(*data) +} \ No newline at end of file diff --git a/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp b/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp index 06a59f76..ee6850a2 100644 --- a/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp +++ b/snmalloc-edp/src/rust-sgx-snmalloc-shim.cpp @@ -34,7 +34,7 @@ extern "C" size_t get_tcs_addr(); // from Rust std -extern "C" void __rust_print_err(const char *m, size_t s); +extern "C" void __rust_print_err(const char* m, size_t s); extern "C" [[noreturn]] void __rust_abort(); /*******************************************************/ @@ -46,7 +46,7 @@ extern "C" [[noreturn]] void abort() __THROW { __rust_abort(); } -// definition needs to match GNU header +// definition needs to match GNU header and will not return an actual errno extern "C" inline int * __attribute_const__ __errno_location (void) __THROW { static int errno; return &errno; @@ -65,7 +65,7 @@ extern "C" inline int * __attribute_const__ __errno_location (void) __THROW { namespace snmalloc { void register_clean_up() { - // TODO: not sure what this is supposed to do + // Unused on SGX abort(); } @@ -73,7 +73,7 @@ class EdpErrorHandler { public: static void print_stack_trace() {} - [[noreturn]] static void error(const char *const str) { + [[noreturn]] static void error(const char* const str) { __rust_print_err(str, strlen(str)); abort(); } diff --git a/snmalloc-edp/tests/global_alloc.rs b/snmalloc-edp/tests/global_alloc.rs index dfdeeafe..ce5ea109 100644 --- a/snmalloc-edp/tests/global_alloc.rs +++ b/snmalloc-edp/tests/global_alloc.rs @@ -1,4 +1,5 @@ use std::{alloc::{self, GlobalAlloc}, cell::Cell, ptr}; +use std::ptr::null_mut; use snmalloc_edp::*; @@ -49,7 +50,7 @@ unsafe fn with_thread_allocator R, R>(f: F) -> R { let r = f(); - THREAD_ALLOC.set(ptr::null_mut()); + THREAD_ALLOC.set(null_mut()); sn_thread_cleanup(allocator.as_mut_ptr()); r @@ -64,13 +65,14 @@ fn test() { #[repr(align(0x1000))] struct Page([u8; 0x1000]); - // allocate a dummy heap - let heap = (*Box::into_raw(vec![Page([0; 4096]); 100].into_boxed_slice())).as_mut_ptr_range(); - - sn_global_init(heap.start as _, heap.end as _); + // allocate a dummy heap + let heap = (*Box::into_raw(vec![Page([0; 4096]); 100].into_boxed_slice())).as_mut_ptr_range(); + let heap_size = heap.end as usize - heap.start as usize; + sn_global_init(heap.start as _, heap_size); } - type AllocTestType = [u64; 20]; + const TEST_ARRAY_SIZE :usize = 20; + type AllocTestType = [u64; TEST_ARRAY_SIZE]; let barrier = std::sync::Barrier::new(2); @@ -79,10 +81,17 @@ fn test() { let barrier = &barrier; s.spawn(move || { unsafe { + // Initialize thread allocator and perform alloc/alloc_zeroed with_thread_allocator(|| { let p1 = System.alloc(alloc::Layout::new::()); barrier.wait(); - let p2 = System.alloc(alloc::Layout::new::()); + let p2 = System.alloc_zeroed(alloc::Layout::new::()); + + let p2_slice = std::slice::from_raw_parts_mut(p2, TEST_ARRAY_SIZE); + for i in 0..TEST_ARRAY_SIZE { + assert_eq!(p2_slice[i], 0); + } + tx.send((p1 as usize, p2 as usize)).unwrap(); }) }; @@ -93,9 +102,15 @@ fn test() { let p1 = System.alloc(alloc::Layout::new::()); barrier.wait(); let p2 = System.alloc(alloc::Layout::new::()); + + // Test realloc + let p3 = System.realloc(p1, alloc::Layout::new::(), TEST_ARRAY_SIZE * 2); + assert_ne!(p3, p2); + (p1 as usize, p2 as usize) }) }; + let (p3, p4) = rx.recv().unwrap(); assert_ne!(p1, p2); assert_ne!(p1, p3); @@ -103,6 +118,7 @@ fn test() { assert_ne!(p2, p3); assert_ne!(p2, p4); assert_ne!(p3, p4); + }) }