From 4b7ee7808b82a8961dd99cd510636953d0d68a46 Mon Sep 17 00:00:00 2001 From: Nathaniel Filardo Date: Wed, 20 May 2020 20:21:11 +0000 Subject: [PATCH 1/2] AAL: new StrictProvenance feature flag --- src/aal/aal.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/aal/aal.h b/src/aal/aal.h index 55b1477..e939f78 100644 --- a/src/aal/aal.h +++ b/src/aal/aal.h @@ -36,6 +36,12 @@ namespace snmalloc * This architecture cannot access cpu cycles counters. */ NoCpuCycleCounters = (1 << 1), + /** + * This architecture enforces strict pointer provenance; we bound the + * pointers given out on malloc() and friends and must, therefore retain + * internal high-privilege pointers for recycling memory on free(). + */ + StrictProvenance = (1 << 2), }; /** From 12111ae7d349cb1a8a0b7baa0eae53acc220f7c4 Mon Sep 17 00:00:00 2001 From: Nathaniel Filardo Date: Wed, 20 May 2020 20:18:59 +0000 Subject: [PATCH 2/2] ds/cdllist: factor out next to base classes Choose between implementations based on aal's requirement of strict provenance. --- src/ds/cdllist.h | 92 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 28 deletions(-) diff --git a/src/ds/cdllist.h b/src/ds/cdllist.h index 1bc39aa..7fe4795 100644 --- a/src/ds/cdllist.h +++ b/src/ds/cdllist.h @@ -7,13 +7,8 @@ namespace snmalloc { - /** - * Special class for cyclic doubly linked non-empty linked list - * - * This code assumes there is always one element in the list. The client - * must ensure there is a sentinal element. - */ - class CDLLNode + template + class CDLLNodeBase { /** * to_next is used to handle a zero initialised data structure. @@ -22,38 +17,86 @@ namespace snmalloc */ ptrdiff_t to_next = 0; - // TODO: CHERI will need a real pointer too - // CDLLNode* next = nullptr; - CDLLNode* prev = nullptr; - - void set_next(CDLLNode* c) + protected: + void set_next(T* c) { - // TODO: CHERI will need a real pointer too - // next = c; to_next = pointer_diff_signed(this, c); } + public: + SNMALLOC_FAST_PATH bool is_empty() + { + return to_next == 0; + } + + SNMALLOC_FAST_PATH T* get_next() + { + return pointer_offset_signed(static_cast(this), to_next); + } + }; + + template + class CDLLNodeBaseNext + { + /** + * Like to_next in the pointer-less case, this version still works with + * zero-initialized data structure. To make `is_empty` work in this case, + * next is set to `nullptr` rather than `this` when the list is empty. + * + */ + + T* next = nullptr; + + protected: + void set_next(T* c) + { + next = (c == static_cast(this)) ? nullptr : c; + } + + public: + SNMALLOC_FAST_PATH bool is_empty() + { + return next == nullptr; + } + + SNMALLOC_FAST_PATH T* get_next() + { + return next == nullptr ? static_cast(this) : next; + } + }; + + template + using CDLLNodeParent = std::conditional_t< + aal_supports, + CDLLNodeBaseNext, + CDLLNodeBase>; + + /** + * Special class for cyclic doubly linked non-empty linked list + * + * This code assumes there is always one element in the list. The client + * must ensure there is a sentinal element. + */ + class CDLLNode : public CDLLNodeParent + { + CDLLNode* prev = nullptr; + public: /** * Single element cyclic list. This is the empty case. */ CDLLNode() { - set_next(this); + this->set_next(this); prev = this; } - SNMALLOC_FAST_PATH bool is_empty() - { - return to_next == 0; - } - /** * Removes this element from the cyclic list is it part of. */ SNMALLOC_FAST_PATH void remove() { - SNMALLOC_ASSERT(!is_empty()); + SNMALLOC_ASSERT(!this->is_empty()); debug_check(); get_next()->prev = prev; prev->set_next(get_next()); @@ -67,13 +110,6 @@ namespace snmalloc #endif } - SNMALLOC_FAST_PATH CDLLNode* get_next() - { - // TODO: CHERI will require a real pointer - // return next; - return pointer_offset_signed(this, to_next); - } - SNMALLOC_FAST_PATH CDLLNode* get_prev() { return prev;