From 06873ac36602df2d5aebcdd2de53e6efe103402d Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Sat, 10 Dec 2022 07:53:15 +0000 Subject: [PATCH] pagemap: don't depend on SNMALLOC_CHECK_CLIENT Instead, take a template parameter for the no-args init() method, so that randomization can be disabled on StrictProvenance architectures (CHERI), where we don't expect it to be useful, even when snmalloc is being built to be otherwise paranoid. Catch callsites up. --- src/snmalloc/backend/globalconfig.h | 12 ++++- src/snmalloc/ds/pagemap.h | 51 +++++++++++--------- src/test/func/domestication/domestication.cc | 8 ++- src/test/func/pagemap/pagemap.cc | 8 ++- 4 files changed, 51 insertions(+), 28 deletions(-) diff --git a/src/snmalloc/backend/globalconfig.h b/src/snmalloc/backend/globalconfig.h index 322536a..8dc08b5 100644 --- a/src/snmalloc/backend/globalconfig.h +++ b/src/snmalloc/backend/globalconfig.h @@ -134,8 +134,16 @@ namespace snmalloc // Initialise key for remote deallocation lists key_global = FreeListKey(entropy.get_free_list_key()); - // Need to initialise pagemap. - Pagemap::concretePagemap.init(); + // Need to initialise pagemap. If SNMALLOC_CHECK_CLIENT is set and this + // isn't a StrictProvenance architecture, randomize its table's location + // within a significantly larger address space allocation. +# if defined(SNMALLOC_CHECK_CLIENT) + static constexpr bool pagemap_randomize = !aal_supports; +# else + static constexpr bool pagemap_randomize = false; +# endif + + Pagemap::concretePagemap.template init(); initialised = true; } diff --git a/src/snmalloc/ds/pagemap.h b/src/snmalloc/ds/pagemap.h index a420249..aa6117b 100644 --- a/src/snmalloc/ds/pagemap.h +++ b/src/snmalloc/ds/pagemap.h @@ -167,7 +167,7 @@ namespace snmalloc /** * Initialise the pagemap without bounds. */ - template + template std::enable_if_t init() { SNMALLOC_ASSERT(!is_initialised()); @@ -176,14 +176,11 @@ namespace snmalloc has_bounds_ == has_bounds, "Don't set SFINAE template parameter!"); static constexpr size_t REQUIRED_SIZE = required_size(); -#ifdef SNMALLOC_CHECK_CLIENT // Allocate a power of two extra to allow the placement of the - // pagemap be difficult to guess. - size_t additional_size = bits::next_pow2(REQUIRED_SIZE) * 4; + // pagemap be difficult to guess if randomize_position set. + size_t additional_size = + randomize_position ? bits::next_pow2(REQUIRED_SIZE) * 4 : 0; size_t request_size = REQUIRED_SIZE + additional_size; -#else - size_t request_size = REQUIRED_SIZE; -#endif auto new_body_untyped = PAL::reserve(request_size); @@ -192,26 +189,32 @@ namespace snmalloc PAL::error("Failed to initialise snmalloc."); } -#ifdef SNMALLOC_CHECK_CLIENT - // Begin pagemap at random offset within the additionally allocated space. - static_assert(bits::is_pow2(sizeof(T)), "Next line assumes this."); - size_t offset = get_entropy64() & (additional_size - sizeof(T)); - auto new_body = pointer_offset(new_body_untyped, offset); + T* new_body; - if constexpr (pal_supports) + if constexpr (randomize_position) { - void* start_page = pointer_align_down(new_body); - void* end_page = pointer_align_up( - pointer_offset(new_body, REQUIRED_SIZE)); - // Only commit readonly memory for this range, if the platform supports - // lazy commit. Otherwise, this would be a lot of memory to have - // mapped. - PAL::notify_using_readonly( - start_page, pointer_diff(start_page, end_page)); + // Begin pagemap at random offset within the additionally allocated + // space. + static_assert(bits::is_pow2(sizeof(T)), "Next line assumes this."); + size_t offset = get_entropy64() & (additional_size - sizeof(T)); + new_body = pointer_offset(new_body_untyped, offset); + + if constexpr (pal_supports) + { + void* start_page = pointer_align_down(new_body); + void* end_page = pointer_align_up( + pointer_offset(new_body, REQUIRED_SIZE)); + // Only commit readonly memory for this range, if the platform + // supports lazy commit. Otherwise, this would be a lot of memory to + // have mapped. + PAL::notify_using_readonly( + start_page, pointer_diff(start_page, end_page)); + } + } + else + { + new_body = static_cast(new_body_untyped); } -#else - auto new_body = static_cast(new_body_untyped); -#endif // Ensure bottom page is committed // ASSUME: new memory is zeroed. PAL::template notify_using( diff --git a/src/test/func/domestication/domestication.cc b/src/test/func/domestication/domestication.cc index 5fbff09..7087ca6 100644 --- a/src/test/func/domestication/domestication.cc +++ b/src/test/func/domestication/domestication.cc @@ -121,7 +121,13 @@ namespace snmalloc int main() { - snmalloc::CustomConfig::Pagemap::concretePagemap.init(); // init pagemap +# if defined(SNMALLOC_CHECK_CLIENT) + static constexpr bool pagemap_randomize = !aal_supports; +# else + static constexpr bool pagemap_randomize = false; +# endif + + snmalloc::CustomConfig::Pagemap::concretePagemap.init(); snmalloc::CustomConfig::domesticate_count = 0; LocalEntropy entropy; diff --git a/src/test/func/pagemap/pagemap.cc b/src/test/func/pagemap/pagemap.cc index 24218b5..84ba536 100644 --- a/src/test/func/pagemap/pagemap.cc +++ b/src/test/func/pagemap/pagemap.cc @@ -81,7 +81,13 @@ void test_pagemap(bool bounded) } else { - pagemap_test_unbound.init(); +#if defined(SNMALLOC_CHECK_CLIENT) + static constexpr bool pagemap_randomize = !aal_supports; +#else + static constexpr bool pagemap_randomize = false; +#endif + + pagemap_test_unbound.init(); pagemap_test_unbound.register_range(low, high - low); }