Skip to content

Introduce AAL StrictProvenance flag, factor CDLList #193

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 21, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
@@ -334,7 +334,7 @@ jobs:
- script: |
set -eo pipefail
ninja clangformat
git diff --exit-code $(Build.SourceVersion)
git diff --exit-code

workingDirectory: build
failOnStderr: true
6 changes: 6 additions & 0 deletions src/aal/aal.h
Original file line number Diff line number Diff line change
@@ -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),
};

/**
90 changes: 63 additions & 27 deletions src/ds/cdllist.h
Original file line number Diff line number Diff line change
@@ -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.
@@ -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());
@@ -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;