Commit Graph

141 Commits

Author SHA1 Message Date
David Chisnall
51e75bca89 Add memcpy with bounds checks.
The memcpy implementation is not completely stupid but is almost
certainly not as good as a carefully tuned and optimised one.

Building snmalloc with FreeBSD's libc memcpy + jemalloc and with this,
each 10 times, does not show a statistically significant performance
difference at 95% confidence.  The snmalloc version has very slightly
lower median and worst-case times.  This is in no way a sensible
benchmark, but it serves as a smoke test for significant performance
regressions.

The CI self-host job now uses the checked memcpy.

This also fixes an off-by-one error in the external bounds.  This is
triggered by ninja, so we will see breakage in CI if it is reintroduced.

In debug builds, we provide a verbose error containing the address of
the allocation, the base and bounds of the allocation, and a backtrace.

The backtrace was broken by the CI cleanup moving the BACKTRACE_HEADER
macro into the SNMALLOC_ namespace.  This is also fixed.

The test involves hijacking `abort`, which doesn't work everywhere.  It
also requires `backtrace` to work in configurations where stack traces
are enabled.  This is disabled in QEMU because `backtrace` appears to
crash reliably in QEMU user mode.

For now, in the -checks build configurations, we are hitting a slow path
in the pagemap on accesses so that the pages that are `PROT_NONE` don't
cause crashes.  These need to be made read-only, but this requires a PAL
change.
2021-09-16 13:53:13 +01:00
Istvan Haller
aedb666cdd Added constness to argv in Opt (#383) 2021-08-31 21:59:43 +01:00
Nathaniel Wesley Filardo
3af9d35099 Plumb LocalState ptrs through to Pagemap accessors
David points out that we might not have a static way to get at the pagemap, so
it is potentially useful to pass pointers to state objects down from the
Allocators.
2021-08-26 16:53:52 +01:00
Matthew Parkinson
44416ed70e Factor sizeclass meta-data for cache locality
This commit splits the sizeclass meta-data to generate better cache
locality for various lookups for checking for size and start of
sizeclasses.

Also, contains some tidying including removing sizeclasses covering
large range. This is left over from an alternative design for large
classes that is no longer in use.
2021-08-26 14:47:56 +01:00
Matthew Parkinson
b52e2a6e27 Expose pthread feature flag
The code was able to use pthread destructors rather than C++ thread
local destructors.  This removes the dependence on a C++ .so on linux.
However, this is not stable on other platforms such as Apple. Where the
C++ thread local state can be cleared before the pthread destructor
runs.
2021-08-25 17:04:08 +01:00
Istvan Haller
33a358e4fe Another attempt to fix CI 2021-08-24 16:18:02 +01:00
Istvan Haller
b7fe8ea654 More comments and improved test 2021-08-24 15:32:51 +01:00
Istvan Haller
df852dba6a Added test and forced initialization of backend when using custom Pool. 2021-08-24 14:19:20 +01:00
Nathaniel Wesley Filardo
c07f5ea7be test/func/pagemap: avoid address_t to void* cast
Instead, tell the iostream to write out hex.  This avoids the CHERI compiler
warning that we're turning a provenance-free value to a pointer.

Co-authored-by: Matthew Parkinson <mattpark@microsoft.com>
2021-08-13 16:46:00 +01:00
Nathaniel Wesley Filardo
87e41559b2 test/func/memory: use pointer_offset to compute pointer offset
This avoids the CHERI compiler warning that we're turning a provenance-free
value to a pointer.

Co-authored-by: Matthew Parkinson <mattpark@microsoft.com>
2021-08-13 16:46:00 +01:00
Nathaniel Wesley Filardo
f103f1c443 test/func/pagemap: use address_t for induction var
Avoids a silent cast from uintptr_t to address_t.
2021-08-13 16:46:00 +01:00
David Chisnall
cd70a7856b Fix fallout from the merge.
- CI merge issues:
   - The malloc shim libraries are renamed.
   - CMake gets very unhappy if you don't enable the C language and
     tries to link with the C compiler instead of the C++ compiler if
     you do enable it.
   - The Ubuntu packages for QEMU install a `binfmt_misc` activator for
     PowerPC64 little-endian, but set the page size to 4 KiB.  We then
     tried to run the tests (which expect 64 KiB pages) and became very
     confused when `mmap` returned 4 KiB-aligned memory.
 - Test failures:
   - Fix all of the issues UBsan found.
     - Underflow in `pointer_offset` when used to add negative offsets.
     - `CoreAlloc`'s `LocalState` accessed on a null `CoreAlloc` pointer.
     - Out of bounds access in the sizeclass list on attempts to access
       more memory than fits in the VA space.
     -
   - There was an integer overflow in `AddressSpace` that could cause it
     to try to allocate a zero-sized object, get a null pointer, and
     then try to do something with 0 - {size of the real allocation}.
   - The malloc tests weren't setting `errno` to 0 before doing
     calling `malloc`, which should set `errno` on failure, and then
     checking that `errno` was 0.
   - Don't call `PAL::error` on PAL allocation failure, return `nullptr`.
     The PALs were inconsistent about that and the new code expects to be
     able to report address-space exhaustion.
   - The malloc checks can behave differently with 0-sized allocations
     on different platforms but were very fragile about their
     expectations.
   - The malloc test didn't report failure for all of the ways that it
     could fail and so was spuriously passing on some platforms.
   - The perf test for external pointer is currently very slow on
     Windows.  The number of loops have been reduced and a timeout added
     for the Windows CI runs.
   - The logic to capture `errno` across calls was using
     `decltype(errno)`, which on some platforms where `errno` is a macro
     evaluated to `int&` and so they captured a reference rather than
     the value and failed to reset `errno`.
   - The Apple PAL can set `errno` on `notify_using` if it's called with
     memory that was not previously passed to `notify_not_using` but was
     not adequately protected against this and so would sometimes cause
     `malloc` to set `errno` to `EINVAL`.
2021-08-06 14:00:56 +01:00
David Chisnall
e8374479f4 Snmalloc2 API cleanups for sandbox use. (#359)
This is the set of changes required for snmalloc2 to be usable by the
process sandboxing code and incorporates some API changes that reduce
the amount of code required to embed snmalloc.  Highlights:

 - Merge the config and back-end classes.
 - Everything in config is now global (all methods are static)
 - The GlobalState class is gone (all global state is managed by global
   methods on the config class)
 - LocalState is now a member of the config class, all methods are
   instance methods.
 - Not every configuration needs to use the lazy initialisation hooks.
   They now need to be provided only if they are used.  If the
   configuration does not provide an `ensure_init` method, it is not
   called.  If it does not provide an `is_initialised` method then the
   global initialisation state is not checked.
 - There is now an `snmalloc::Options` class that default initialises
   itself to the default behaviour.  Every configuration must provide a
   `constexpr` instance of this class.  Each flag can be separately
   overridden and new flags can be added without breaking any existing
   API consumers.

The config classes are moved into the backend directory.
2021-08-05 15:08:12 +01:00
Matthew Parkinson
0cfa8f2cff Remove globalconfig.h includes. 2021-07-23 10:21:27 +01:00
Matthew Parkinson
d6bae72b20 Improve debugging for fixed_region 2021-07-23 07:23:35 +01:00
Matthew Parkinson
d965ab2645 Print stack traces for segfault
Trap the segfault signal, and call the platform error.  In most cases
for CI this will print a stack trace.
2021-07-23 07:23:35 +01:00
Matthew Parkinson
5d0ae71423 Remove at_least
The Pal was providing policy for overallocating a block of memory to
achieve alignment make that part of the backend.
The backend should be responsible for layout policy.
2021-07-21 09:36:06 +01:00
Matthew Parkinson
02d2ab8f7e Pagemap requires registration of used space
This PR exposes a pagemap interface to specify ranges that are being
used. The overall invariant is that any memory in the address space
manager has the pagemap committed. This means that individual operations
do not need to commit entries.

This is important for Windows that does not support lazy commit.  It is
also important if we want to PROT_NONE most of the pagemap to reduce the
risk of memory safety issues getting access to the pagemap.

There are minor changes to test to pull memory directly from the Pal.
There are also bug fixes in the pagemap tests.
2021-07-21 09:36:06 +01:00
Matthew Parkinson
da01d5b4ca Remove address space usage from Pagemap.
The pagemap allocates it self directly either from

  * the original fixed address range it is supplied, and returns the
    remaining space after the pagemap is removed; or
  * directly allocated from the PAL without using the address space
    manager.

This change in layering is required for the next commit, which imposes
the invariant that the pagemap has been committed for all spaced managed
by the address space manager.
2021-07-21 09:36:06 +01:00
Istvan Haller
d0ecba5280 Improved OEPal integration with the new snmalloc architecture (#346)
* Improved OEPal integration with the new snmalloc architecture

* Applied PR feedback
2021-07-15 15:06:47 +01:00
Matthew Parkinson
4b9ead8066 Fix register_clean_up being called with ScopedAllocator. (#344) 2021-07-12 19:50:36 +01:00
Matthew Parkinson
f0e2ab702a Major refactor of snmalloc (#343)
# Pagemap
 
The Pagemap now stores all the meta-data for the object allocation. The meta-data in the pagemap is effectively a triple of the sizeclass, the remote allocator, and a pointer to a 64 byte block of meta-data for this chunk of memory. By storing the pointer to a block, it allows the pagemap to handle multiple slab sizes without branching on the fast path. There is one entry in the pagemap per 16KiB of address space, but by using the same entry in the pagemap for 4 adjacent entries, then we can treat a 64KiB range can be treated as a single slab of allocations.

This change also means there is almost no capability amplification required by the implementation on CHERI for finding meta-data. The only amplification is required, when we change the way a chunk is used to a size of object allocation.


# Backend

There is a second major aspect of the refactor that there is now a narrow API that abstracts the Pagemap, PAL and address space management. This should better enable the compartmentalisation and makes it easier to produce alternative backends for various research directions. This is a template parameter that can be used to specialised by the front-end in different ways.

# Thread local state

The thread local state has been refactored into two components, one (called 'localalloc') that is stored directly in the TLS and is constant initialised, and one that is allocated in the address space (called 'coreallloc') which is lazily created and pooled.

# Difference

This removes Superslabs/Medium slabs as there meta-data is now part of the pagemap.
2021-07-12 15:53:36 +01:00
Nathaniel Filardo
8390a70a48 Fix static-sized alloc paths, add compilation test
The CapPtr refactoring was largely compiler guided; unfortunately, it turns out
that the static-sized alloc function is not well exercised.  As such, some type
errors and unnecessary unsafety lurked behind missing template instantiation.

Correct those and add calls to the test harness to make sure we always generate
at least one instance of each small/medium/large case.  While here, it doesn't
hurt to make sure that we call all three possible dealloc() flavors as well.
This will, if nothing else, force instantiation of the static-sized dealloc
template as well.
2021-04-20 12:17:46 +01:00
Nathaniel Filardo
f7821e11eb SP: LargeAlloc return CBChunk & chase consequences
Even if we opt not to bound these pointers internally (if they aren't headed out
to the user program or we later derive bounded pointers), they should still be
annotated as something other than CBArena, ensuring that we do not attempt to
use them for general amplification.
2021-04-09 12:39:29 +01:00
Nathaniel Filardo
6a7e82463c SP: MemoryProviderStateMixin, AddressSpaceManager
* The AddressSpaceManager now requests address space in specified granule
  sizes and registers those allocations with an external ArenaMap.

* The DefaultArenaMap is a (somewhat erroneously named) Pagemap sparse array /
  tree for these provenance roots.  Nothing is stored on non-StrictProvenance
  architectures.

* In the Sandbox test, give an example of a different ArenaMap structure, which
  confines amplification to sandbox memory.

* Adjust some other tests to compile.
2021-04-09 12:39:29 +01:00
Nathaniel Filardo
e31751fc94 Add workaround for MSVC vs. CapPtr constructor 2021-04-09 12:39:29 +01:00
Nathaniel Filardo
d9ee19a16c SP: use CapPtr<>s in address_space, largealloc 2021-04-09 12:39:29 +01:00
Nathaniel Filardo
005f5787ef SP: start plumbing CapPtr<>s 2021-04-09 12:39:29 +01:00
Matthew Parkinson
7202f9e091 Handle UB that was not exercised originally. 2021-04-07 11:43:53 +01:00
Nathaniel Filardo
0acf166eec sandbox test: use snmalloc to allocate sandbox arena
We're going to try calling (our, out-of-sandbox) ->dealloc() on pointers into
sandbox memory, so, when CHERIfied, we will need amplification authority over
that memory.  Rather than asking the PAL for memory directly, ask the
out-of-sandbox snmalloc so that it will, on CHERI, go through its whole dance
with its AuthMap.
2021-04-06 16:25:57 +01:00
Matthew Parkinson
52a1a9cce1 Changes to OE Pal. 2021-04-06 14:09:18 +01:00
Matthew Parkinson
5419e58633 Add random to Open Enclave Pal 2021-04-06 14:09:18 +01:00
Matthew Parkinson
63f231f484 Bug fix for superslab meta-data (#302)
* Replace time measuring macro

The DO_TIME macro was used originally to get performance numbers. The
macro makes tests hard to debug. This commit replaces it with a proper
C++ class with destructor.

* Bug fix

If the superslab meta data is large, then the calculation for the
sizeclasses that could use the short slab was incorrect.  This fixes
that calculation.

Co-authored-by: Nathaniel Wesley Filardo <nfilardo@microsoft.com>
2021-03-23 12:42:11 +00:00
Matthew Parkinson
d56a99a747 Remove USE_MEASURE
The initial performance monitoring for snmalloc used timing of small
operations to guide the design. This feature has not been maintained or
used for several years.

This commit removes the feature.
2021-03-21 19:00:54 +00:00
Matthew Parkinson
8824622136 Better reciprocal division and modulus.
The previous reciprocal division branch on the prime that the sizeclass
was constructed from. All sizeclasses can be represented as
  2^n * {1,3,5,7}
This lead to a very small table, but some work to calculate the
appropriate shifts and multiplications to implement reciprocal division.

This commit uses a completely uniform representation for every
sizeclass using a lookup table.  Due to the precise ranges that we query
the modulus and rounding on, we can do this much more efficiently.

The func-release-rounding exhaustively tests all the queries we are
interested in.
2021-03-19 20:11:15 +00:00
Nathaniel Filardo
f295a3f191 alloc: de-static external_pointer
Like alloc_size, this will require amplification internally.

This patch also restores performance to the status quo ante; Clang can once
again see enough to generate the same code as it did before de-static-ing
alloc_size.
2021-03-16 09:29:19 +00:00
Nathaniel Filardo
1042fc908a alloc: de-static alloc_size
We're going to need to amplify the pointer and that's going to require access
to our AddressSpaceManager, which we only get non-statically through our
LargeAlloc.

This patch unto itself makes the world slower, perhaps because Clang can't see
the certainty of aliasing of the static and non-static paths to the same
structure.  However, when we also de-static external_pointer, that goes away and
things return to the status quo ante.
2021-03-16 09:29:19 +00:00
Nathaniel Filardo
263e9562c0 NFC: Feed Pagemap its primitive allocator as template arg
This will let us use Pagemaps further down the dependency stack (specifically,
we're going to want a Pagemap inside the AddressSpaceManager) by letting us
manually tie the knot rather than rely on GlobalVirtual and
default_memory_provider() being defined by the time we want a Pagemap.
2021-03-16 09:29:19 +00:00
Nathaniel Filardo
6250428c3d NFC: Further disentangle chunkmap and pagemap
- Make GlobalPagemapTemplate and ExternalGlobalPagemap generic in the type of
  the pagemap they're encapsulating.

  We're going to want to use these for other kinds of pagemaps in the near
  future.

- Rename snmalloc_pagemap_global_get to snmalloc_chunkmap_global_get.

- Rename GlobalPagemap to GlobalChunkmap.
2021-03-16 09:29:19 +00:00
Nathaniel Filardo
8da12f5af8 NFC: tests: size_t and uintptr_t are not interchangable 2021-03-16 09:29:19 +00:00
Nathaniel Filardo
6259457790 Add -Wconversion to clang builds
MSVC has strong opinions on implicit conversions as used in CI, while Clang both
locally and in CI has weaker opinions.  In an effort to avoid subsequent
roundtrips through CI, make clang more strict.  Adding -Wconversion definitely
increases the strength of clang's opinions, apparently to include frowning on
some that even MSVC considers OK, so go make explicit the current implicit
behavior.
2021-03-01 20:18:01 +00:00
Matthew Parkinson
8840b386bc Make LowMemoryNotification object allocated (#281)
* Make LowMemoryNotification object allocated

This makes a separate allocation for the callback object.  This makes
it easier for different callbacks to be used.

* Add reserve_with_leftover to address_space

The address_space now supports reserving for non-power of 2 allocations
and the space that is used for rounding up is retained by the
address_space.  This means that we can more tightly pack the allocators
internal objects.
2021-02-23 14:51:44 +00:00
David Chisnall
c33f355736 Fix the sandbox use case and add a test. (#269)
Summary of changes:

- Add a new PAL that doesn't allocate memory, which can be used with a
  memory provider that is pre-initialised with a range of memory.
- Add a `NoAllocation` PAL property so that the methods on a PAL that 
  doesn't support dynamically reserving address space will never be
  called and therefore don't need to be implemented.
- Slightly refactor the memory provider class so that it has a narrower
  interface with LargeAlloc and is easier to proxy.
- Allow the address space manager and the memory provider to be
  initialised with a range of memory.

This may eventually also remove the need for (or, at least, simplify)
the Open Enclave PAL.

This commit also ends up with a few other cleanups:

 - The `malloc_useable_size` CMake test that checks whether the
   parameter is const qualified was failing on FreeBSD where this
   function is declared in `malloc_np.h` but where including
   `malloc.h` raises an error.  This should now be more robust.
 - The BSD aligned PAL inherited from the BSD PAL, which does not
   expose aligned allocation. This meant that it exposed both the
   aligned and non-aligned allocation interfaces and so happily
   accepted incorrect `constexpr` if blocks that expected one or 
   the other but accidentally required both to exist. The unaligned
   function is now deleted so the same failures that appear in CI should
   appear locally for anyone using this PAL.
2021-01-11 14:06:51 +00:00
David Chisnall
4837c82489 Fix external pagemap usage. (#221)
At some point in the refactoring, these were broken.
2021-01-08 13:21:37 +00:00
Matthew Parkinson
923705e514 Natural alignment for USE_MALLOC (#248)
* Add concept of natural alignment to tests.

snmalloc naturally aligns blocks very heavily, so that
the largest power-of-two in the rounded size is the alignment.
This checks that in the test, and provides a method for
finding the natural alignment of a block.

* Improve USE_MALLOC to provide alignment

snmalloc provides a lot of alginment guarantees. This ensures that when
we pass through to the system allocator we still get those alignment
guarantees.

The commit also fixes the tests to work with USE_MALLOC, and builds a
set of unit tests for ctest to check behaviour.
2020-09-28 10:08:19 +01:00
Matthew Parkinson
f89f78ad46 Fix bug in pagemap when index has many levels
The pagemap was double incrementing the index level.  This did not
exhibit in any use case of the pagemap as it only used 0 or 1 level of
intermediate index for all current use cases.

This commit fixes the bug, and adds a test that uses the pagemap in a
different configuration that has multiple levels of intermediate index
node.
2020-09-24 11:10:30 +01:00
Nathaniel Filardo
1e8d0bd743 MemoryProviderStateMixin is not a PAL 2020-09-09 12:55:48 +01:00
Matthew Parkinson
77ebff6909 Added simple stats tracking memory usage (#241)
These statistics can be maintained with effectively zero cost to
realistic applications.  They do not track the precise amount of
memory used, but are an over-approximation.
2020-08-28 14:01:52 +01:00
Matthew Parkinson
234c0e2e8e Clang format 2020-08-26 17:51:46 +01:00
Matthew Parkinson
0728db1413 Fixes to ctz on Windows Clang. 2020-08-26 17:51:46 +01:00