Skip to content

Commit

Permalink
Merge pull request #193 from nwf/aal-strict-provenance
Browse files Browse the repository at this point in the history
Introduce AAL StrictProvenance flag, factor CDLList
  • Loading branch information
mjp41 authored May 21, 2020
2 parents 8dad07f + 12111ae commit 97e695b
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 27 deletions.
6 changes: 6 additions & 0 deletions src/aal/aal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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),
};

/**
Expand Down
90 changes: 63 additions & 27 deletions src/ds/cdllist.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<typename T>
class CDLLNodeBase
{
/**
* to_next is used to handle a zero initialised data structure.
Expand All @@ -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<T*>(this), to_next);
}
};

template<typename T>
class CDLLNodeBaseNext
{
/**
* Single element cyclic list. This is the empty case.
* 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.
*
*/
CDLLNode()

T* next = nullptr;

protected:
void set_next(T* c)
{
set_next(this);
prev = this;
next = (c == static_cast<T*>(this)) ? nullptr : c;
}

public:
SNMALLOC_FAST_PATH bool is_empty()
{
return to_next == 0;
return next == nullptr;
}

SNMALLOC_FAST_PATH T* get_next()
{
return next == nullptr ? static_cast<T*>(this) : next;
}
};

template<typename T>
using CDLLNodeParent = std::conditional_t<
aal_supports<StrictProvenance>,
CDLLNodeBaseNext<T>,
CDLLNodeBase<T>>;

/**
* 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>
{
CDLLNode* prev = nullptr;

public:
/**
* Single element cyclic list. This is the empty case.
*/
CDLLNode()
{
this->set_next(this);
prev = this;
}

/**
* 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());
Expand All @@ -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;
Expand Down

0 comments on commit 97e695b

Please sign in to comment.