Skip to content

Commit

Permalink
Initial CHERI support for free rings
Browse files Browse the repository at this point in the history
  • Loading branch information
nwf-msr committed Mar 12, 2024
1 parent fabf590 commit 87059ba
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 8 deletions.
8 changes: 8 additions & 0 deletions src/snmalloc/backend/backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,14 @@ namespace snmalloc
local_state.get_object_range()->dealloc_range(arena, size);
}

SNMALLOC_FAST_PATH static capptr::Alloc<void>
capptr_rederive_alloc(capptr::Alloc<void> a, size_t objsize)
{
return capptr_to_user_address_control(
Aal::capptr_bound<void, capptr::bounds::AllocFull>(
Authmap::amplify(a), objsize));
}

template<bool potentially_out_of_range = false>
SNMALLOC_FAST_PATH static const PagemapEntry& get_metaentry(address_t p)
{
Expand Down
10 changes: 8 additions & 2 deletions src/snmalloc/mem/corealloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -769,8 +769,14 @@ namespace snmalloc
is_start_of_object(entry.get_sizeclass(), address_cast(msg)),
"Not deallocating start of an object");

auto [curr, length] = RemoteMessage::open_free_ring(
msg, freelist::Object::key_root, meta->as_key_tweak(), domesticate);
size_t objsize = sizeclass_full_to_size(entry.get_sizeclass());

auto [curr, length] = RemoteMessage::template open_free_ring<Config>(
msg,
objsize,
freelist::Object::key_root,
meta->as_key_tweak(),
domesticate);

// Update the head and the next pointer in the free list.
meta->free_queue.append_segment(
Expand Down
26 changes: 20 additions & 6 deletions src/snmalloc/mem/remoteallocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ namespace snmalloc
new (last.unsafe_ptr()) RemoteMessage());
self->free_ring.prev = last_prev;

// XXX CHERI
// XXX On CHERI, we could do a fair bit better if we had a primitive for
// extracting and discarding the offset. That probably beats the dance
// done below, but it should work as it stands.

auto n = freelist::HeadPtr::unsafe_from(
unsafe_from_uintptr<freelist::Object::T<>>(
Expand Down Expand Up @@ -84,9 +86,11 @@ namespace snmalloc
.as_reinterpret<RemoteMessage>();
}

template<typename Domesticator_queue>
static std::pair<freelist::HeadPtr, size_t> open_free_ring(
template<SNMALLOC_CONCEPT(IsConfigLazy) Config, typename Domesticator_queue>
SNMALLOC_FAST_PATH static std::pair<freelist::HeadPtr, size_t>
open_free_ring(
capptr::Alloc<RemoteMessage> m,
size_t objsize,
const FreeListKey& key,
address_t key_tweak,
Domesticator_queue domesticate)
Expand All @@ -96,10 +100,20 @@ namespace snmalloc

size_t decoded_size = encoded & bits::mask_bits(MAX_CAPACITY_BITS);

/*
* Derive an out-of-bounds pointer to the next allocation, then use the
* authmap to reconstruct an in-bounds version, which we then immediately
* bound and rewild.
*
* XXX See above re: doing better on CHERI.
*/
auto decoded_next =
capptr_rewild(pointer_offset_signed(
m, static_cast<intptr_t>(encoded) >> MAX_CAPACITY_BITS))
.as_static<freelist::Object::T<>>();
capptr_rewild(
Config::Backend::capptr_rederive_alloc(
pointer_offset_signed(
m, static_cast<intptr_t>(encoded) >> MAX_CAPACITY_BITS),
objsize))
.template as_static<freelist::Object::T<>>();

auto next = domesticate(decoded_next);

Expand Down

0 comments on commit 87059ba

Please sign in to comment.