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.
This commit is contained in:
Nathaniel Wesley Filardo
2022-12-10 07:53:15 +00:00
committed by Nathaniel Filardo
parent 30da31d245
commit 06873ac366
4 changed files with 51 additions and 28 deletions

View File

@@ -134,8 +134,16 @@ namespace snmalloc
// Initialise key for remote deallocation lists // Initialise key for remote deallocation lists
key_global = FreeListKey(entropy.get_free_list_key()); key_global = FreeListKey(entropy.get_free_list_key());
// Need to initialise pagemap. // Need to initialise pagemap. If SNMALLOC_CHECK_CLIENT is set and this
Pagemap::concretePagemap.init(); // 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<StrictProvenance>;
# else
static constexpr bool pagemap_randomize = false;
# endif
Pagemap::concretePagemap.template init<pagemap_randomize>();
initialised = true; initialised = true;
} }

View File

@@ -167,7 +167,7 @@ namespace snmalloc
/** /**
* Initialise the pagemap without bounds. * Initialise the pagemap without bounds.
*/ */
template<bool has_bounds_ = has_bounds> template<bool randomize_position, bool has_bounds_ = has_bounds>
std::enable_if_t<!has_bounds_> init() std::enable_if_t<!has_bounds_> init()
{ {
SNMALLOC_ASSERT(!is_initialised()); SNMALLOC_ASSERT(!is_initialised());
@@ -176,14 +176,11 @@ namespace snmalloc
has_bounds_ == has_bounds, "Don't set SFINAE template parameter!"); has_bounds_ == has_bounds, "Don't set SFINAE template parameter!");
static constexpr size_t REQUIRED_SIZE = required_size(); static constexpr size_t REQUIRED_SIZE = required_size();
#ifdef SNMALLOC_CHECK_CLIENT
// Allocate a power of two extra to allow the placement of the // Allocate a power of two extra to allow the placement of the
// pagemap be difficult to guess. // pagemap be difficult to guess if randomize_position set.
size_t additional_size = bits::next_pow2(REQUIRED_SIZE) * 4; size_t additional_size =
randomize_position ? bits::next_pow2(REQUIRED_SIZE) * 4 : 0;
size_t request_size = REQUIRED_SIZE + additional_size; size_t request_size = REQUIRED_SIZE + additional_size;
#else
size_t request_size = REQUIRED_SIZE;
#endif
auto new_body_untyped = PAL::reserve(request_size); auto new_body_untyped = PAL::reserve(request_size);
@@ -192,26 +189,32 @@ namespace snmalloc
PAL::error("Failed to initialise snmalloc."); PAL::error("Failed to initialise snmalloc.");
} }
#ifdef SNMALLOC_CHECK_CLIENT T* new_body;
// 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<PAL>() & (additional_size - sizeof(T));
auto new_body = pointer_offset<T>(new_body_untyped, offset);
if constexpr (pal_supports<LazyCommit, PAL>) if constexpr (randomize_position)
{ {
void* start_page = pointer_align_down<OS_PAGE_SIZE>(new_body); // Begin pagemap at random offset within the additionally allocated
void* end_page = pointer_align_up<OS_PAGE_SIZE>( // space.
pointer_offset(new_body, REQUIRED_SIZE)); static_assert(bits::is_pow2(sizeof(T)), "Next line assumes this.");
// Only commit readonly memory for this range, if the platform supports size_t offset = get_entropy64<PAL>() & (additional_size - sizeof(T));
// lazy commit. Otherwise, this would be a lot of memory to have new_body = pointer_offset<T>(new_body_untyped, offset);
// mapped.
PAL::notify_using_readonly( if constexpr (pal_supports<LazyCommit, PAL>)
start_page, pointer_diff(start_page, end_page)); {
void* start_page = pointer_align_down<OS_PAGE_SIZE>(new_body);
void* end_page = pointer_align_up<OS_PAGE_SIZE>(
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<T*>(new_body_untyped);
} }
#else
auto new_body = static_cast<T*>(new_body_untyped);
#endif
// Ensure bottom page is committed // Ensure bottom page is committed
// ASSUME: new memory is zeroed. // ASSUME: new memory is zeroed.
PAL::template notify_using<NoZero>( PAL::template notify_using<NoZero>(

View File

@@ -121,7 +121,13 @@ namespace snmalloc
int main() int main()
{ {
snmalloc::CustomConfig::Pagemap::concretePagemap.init(); // init pagemap # if defined(SNMALLOC_CHECK_CLIENT)
static constexpr bool pagemap_randomize = !aal_supports<StrictProvenance>;
# else
static constexpr bool pagemap_randomize = false;
# endif
snmalloc::CustomConfig::Pagemap::concretePagemap.init<pagemap_randomize>();
snmalloc::CustomConfig::domesticate_count = 0; snmalloc::CustomConfig::domesticate_count = 0;
LocalEntropy entropy; LocalEntropy entropy;

View File

@@ -81,7 +81,13 @@ void test_pagemap(bool bounded)
} }
else else
{ {
pagemap_test_unbound.init(); #if defined(SNMALLOC_CHECK_CLIENT)
static constexpr bool pagemap_randomize = !aal_supports<StrictProvenance>;
#else
static constexpr bool pagemap_randomize = false;
#endif
pagemap_test_unbound.init<pagemap_randomize>();
pagemap_test_unbound.register_range(low, high - low); pagemap_test_unbound.register_range(low, high - low);
} }