Hardening access to meta data

Introduce a wrapper that ensure various fields of meta data, represent
valid indexes into the the address space, and not beyond the current
slab/superslab.
This commit is contained in:
Matthew Parkinson
2019-01-24 10:48:16 +00:00
parent 2083b29c9b
commit 294efe8e03
3 changed files with 40 additions and 9 deletions

View File

@@ -32,6 +32,34 @@ namespace snmalloc
}
};
/**
* Wrapper for wrapping values.
*
* Wraps on read. This allows code to trust the value is in range, even when
* there is a memory corruption.
**/
template<size_t length, typename T>
class Mod
{
static_assert(length == bits::next_pow2_const(length),
"Must be a power of two.");
private:
T value;
public:
operator T()
{
return (T)(value & (length - 1));
}
T& operator=(const T v)
{
value = v;
return value;
}
};
template<size_t length, typename T>
class ModArray
{

View File

@@ -1,6 +1,7 @@
#pragma once
#include "../ds/dllist.h"
#include "../ds/helpers.h"
#include "sizeclass.h"
namespace snmalloc
@@ -51,11 +52,11 @@ namespace snmalloc
// The terminal value in the free list, and the terminal value in
// the SlabLink previous field will alias. The SlabLink uses ~0 for
// its terminal value to be a valid terminal bump ptr.
uint16_t head;
Mod<SLAB_SIZE, uint16_t> head;
// When a slab has free space it will be on the has space list for
// that size class. We use an empty block in this slab to be the
// doubly linked node into that size class's free list.
uint16_t link;
Mod<SLAB_SIZE, uint16_t> link;
uint8_t sizeclass;
uint8_t next;

View File

@@ -1,5 +1,6 @@
#pragma once
#include "allocslab.h"
#include "metaslab.h"
#include "../ds/helpers.h"
#include <cstring>
@@ -30,7 +31,7 @@ namespace snmalloc
// are the relative offset to the next entry minus 1. This means that
// all zeros is a list that chains through all the blocks, so the zero
// initialised memory requires no more work.
uint8_t head;
Mod<SLAB_COUNT, uint8_t> head;
// Represents twice the number of full size slabs used
// plus 1 for the short slab. i.e. using 3 slabs and the
@@ -180,15 +181,16 @@ namespace snmalloc
template<typename MemoryProvider>
Slab* alloc_slab(uint8_t sizeclass, MemoryProvider& memory_provider)
{
Slab* slab = (Slab*)((size_t)this + ((size_t)head << SLAB_BITS));
uint8_t h = head;
Slab* slab = (Slab*)((size_t)this + ((size_t)h << SLAB_BITS));
uint8_t n = meta[head].next;
uint8_t n = meta[h].next;
meta[head].head = get_slab_offset(sizeclass, false);
meta[head].sizeclass = sizeclass;
meta[head].link = SLABLINK_INDEX;
meta[h].head = get_slab_offset(sizeclass, false);
meta[h].sizeclass = sizeclass;
meta[h].link = SLABLINK_INDEX;
head = head + n + 1;
head = h + n + 1;
used += 2;
if (decommit_strategy == DecommitAll)