Commit Graph

164 Commits

Author SHA1 Message Date
Nathaniel Wesley Filardo
06873ac366 pagemap: don't depend on SNMALLOC_CHECK_CLIENT
Instead, take a template parameter for the no-args init() method, so
that randomization can be disabled on StrictProvenance architectures
(CHERI), where we don't expect it to be useful, even when snmalloc is
being built to be otherwise paranoid.

Catch callsites up.
2022-12-14 17:46:53 +00:00
Matthew Parkinson
ddc5703cc8 Expose pool sort. (#565) 2022-10-10 17:13:10 +01:00
Matthew Parkinson
2f8f376db8 Pagemap Rounding (#558)
* Extend pagemap test

Check for possible overlap between heap and pagemap, but writing and
reading the heap.

* Return unalign memory from the pagemap

This commit allows the pagemap to return unaligned range of memory. This
means that bump allocation of multiple pagemaps doesn't
waste as much space.
2022-09-17 14:30:13 +01:00
Matthew Parkinson
11c18082d6 Make smallbuddy handle larger requests correctly (#556)
* Fail more abruptly if the bounds are not exact.

* Move bounding from Pool into Backend.

This commit makes the rounding and the bounding occur in the same
function.

* Enable smallbuddyrange to handle larger requests

The smallbuddy can now pass the larger requests up the range chain if
it cannot satisfy it itself.

* Test larger requests for meta-data.
2022-09-14 12:12:06 +01:00
Nathaniel Wesley Filardo
0ea12d9725 test/func/cheri: verify representability of sizeclasses 2022-09-14 10:10:14 +01:00
Nathaniel Wesley Filardo
c4311b4a41 func/cheri: probe memcpy correctness
Fling some misaligned cases at our memcpy and check the results
2022-09-07 13:05:49 +01:00
Nathaniel Wesley Filardo
09bc0c6be7 NFC: external_pointer address_cast earlier
Make it easier to justify our avoidance of capptr_from_client and
capptr_reveal in external_pointer by performing address_cast earlier.
In particular, with this change, we can see that the pointer (and so its
authority, in CHERI) is not passed to any called function other than
address_cast and pointer_offset, and so authority is merely propagated
and neither exercised nor amplified.

Remove the long-disused capptr_reveal_wild, which was added for earlier
versions of external_pointer.
2022-07-07 16:57:47 +01:00
Nathaniel Wesley Filardo
b2c75dffb7 NFC: rename ConceptBound to IsBound 2022-07-07 16:57:47 +01:00
Nathaniel Wesley Filardo
da19291d4e RFC: Add tests for some CHERI-specific behaviors 2022-06-09 01:05:04 +01:00
Nathaniel Wesley Filardo
095e8f13db func-malloc: expand CHERI tests to check no-VMEM 2022-06-09 01:05:04 +01:00
Nathaniel Wesley Filardo
f41bb321f7 RFC: Hide CapPtr constructor
Expose a static CapPtr<T,B>::unsafe_from() and use that everywhere instead
(though continue to allow implicit and explicit construction of CapPtr from
nullptr).
2022-06-09 01:05:04 +01:00
David CARLIER
e7e558badf exposes macOs malloc_good_size (#538) 2022-06-07 16:09:55 +01:00
Matthew Parkinson
03c9da6aa4 Refactor interface between backend and frontend (#530)
* Rename to use Config, rather than StateHandle/Globals/Backend
* Make Backend a type on Config that contains the address space management implementation
* Make Ranges part of the Backend configuration, so we can reuse code for different ways of managing memory
* Pull the common chains of range definitions into separate files for reuse.
* Move PagemapEntry to CommonConfig
* Expose Pagemap through backend, so frontend doesn't see Pagemap directly
* Remove global Pal and use DefaultPal, where one is not pass explicitly.

Co-authored-by: David Chisnall <davidchisnall@users.noreply.github.com>
Co-authored-by: Nathaniel Filardo <105816689+nwf-msr@users.noreply.github.com>
2022-05-31 10:45:04 +01:00
Robert Norton
f277cf2f00 Refactor capptr_domesticate SFINAE to make more statically safe.
This refactoring was provided by David.  Previously if a backend
provided a capptr_domesticate function with the wrong type it would be
silently ignored.  This change requires backends to explicitly opt in
to domestication via a new Backend::Option and ensures the compiler
will loudly complain if there is a mismatch.
2022-04-28 10:02:42 +01:00
Matthew Parkinson
943bae1b34 Minimal example of #506 2022-04-11 21:07:05 +01:00
David Chisnall
f6e9796bbc Introduce header layering (#503)
See src/snmalloc/README.md for an explanation of the layers.

Some other cleanups on the way:

Fine-grained stats support is now gone.

It's been broken for two years, it depends on iostream (which then
causes linker failures with libstdc++) and it's collecting the wrong
stats for the new design.  After discussion with @mjp41, it's better to
remove it and introduce new stats support later, rather than keep broken
code in the main branch.

Tracing was controlled with a preprocessor macro, now there's also a
CMake option.
2022-04-06 09:59:33 +01:00
David Chisnall
65ee6b2a2f Refactor MetaSlab / MetaCommon. (#501)
MetaCommon is now gone.  The back end must provide a SlabMetadata,
which must be a subtype of MetaSlab (i.e. MetaSlab or a subclass of
MetaSlab).  It may add additional state here.

The MetaEntry is now templated on the concrete subclass of MetaSlab that
the back-end uses.  The MetaEntry still stores this as a `uintptr_t` to
allow easier toggling of the boundary bit but the interfaces are all in
terms of stable types now.

Also some tidying of names (SharedStateHandle is now called Backend).

In a follow-on PR, we can then remove the chunk field from the
BackendMetadata in the non-CHERI back end and allow back ends that don't
require extra state to use MetaSlab directly.

Other cleanups:

 - Remove backend/metatypes, define the types that the front end expects
   in mem/metaslab.  The back end may extend them but these types define
   part of the contract between the front and back ends.
 - Remove FrontendMetaEntry and fold its methods into MetaEntry.
 - For example purposes, the default back end now extends MetaEntry.
   This also ensures that nothing in the front end depends on the
   specific type of MetaEntry.
 - Some things now have more sensible names.

The meta entry now operates in one of three modes:

 - When owned by the front end, it stores a pointer to a remote, a
   pointer to some MetaSlab subclass, and a sizeclass.
 - When owned by the back end, it stores two back-end defined values
   that must fit in the bits of `uintptr_t` that are not reserved for
   the MetaEntry itself.
 - When not owned by either, it can be queried as if owned by the front
   end.

The red-black tree has been refactored to allow the holder to be a
wrapper type, removing all of the Holder* and Holder& uses and treating
it uniformly as a value type that can be used to access the contents.

The chunk field is fone from the slab medatada.
This will need to be added back in the CHERI back ends, but it's a
back-end policy.  The back end can choose to use it or not, depending on
whether it can safely convert between an Alloc-bounded pointer and a
Chunk-bounded pointer.

The term 'metaslab' originated in snmalloc 1 to mean a slab of slabs.
In the snmalloc2 branch it was repurposed to mean metadata about a
slab.  To make this clearer, all uses of metaslab are now gone and have
been renamed to slab metadata.  The frontend metadata classes are all
prefixed Frontend and some extra invariants are checked with
`static_assert`.
2022-04-01 17:32:53 +01:00
Matthew Parkinson
821620133d Remove ChunkAllocator 2022-03-24 08:01:09 +00:00
Matthew Parkinson
2ff2cdf8ff Add test for external pointer on stack
The external pointer function should work on any memory.  This checks
it works for the stack.
2022-03-21 23:21:24 +00:00
Nathaniel Wesley Filardo
26324e8bfc Add and plumb unsafe_{to,from}_uintptr<T> casts
These encapsulate the wildly powerful reinterpret_cast<> operator where one side
is a uintptr_t and the other is a native pointer.  In both cases we require the
pointer type to be explicitly given.
2022-03-18 15:06:01 +00:00
Nathaniel Wesley Filardo
4ad99d7392 Downgrade some casts
Do a quick sweep through the codebase to eliminate some reinterpret_cast<>s
where less fire power would do just fine.
2022-03-18 15:06:01 +00:00
Matthew Parkinson
5287000453 Buddy (#468)
# Small changes before rewrite

* Additional bit in remote allocator to prevent type confusion with the backend.
* Move Chunk allocator to backend.
* Improvements to RedBlack tree
* Expose message from Pal

# Complete backend rewrite

This provides two key changes:

* We use buddy allocators to allow memory to reconsolidated
* The backend is factored into a series of small operations that
    allocate and deallocate memory.

The backend now uses "Ranges", there are two ranges that don't require a
parent range:
* EmptyRange - Never returns any memory
* PalRange - Returns memory from the platform.

All other ranges require a parent range to supply memory to them.  Some
ranges support both allocation and deallocation, and some just
deallocation.  For instance,  CommitRange supports both, and maps
requests to the parent range, but will Commit and Decommit the memory.

As the ranges perform only a single task, they are generally small and
easy to follow.  The two exceptions to this are the two BuddyRanges
(Large and Small).  Large is for CHUNK_SIZE and above blocks, while
Small is for below CHUNK_SIZE blocks.  Both are implemented with a buddy
allocator, but the SmallBuddyRange uses in place meta-data, while the
LargeBuddyRange uses the pagemap for its meta-data.  This means the
LargeBuddyRange can keep the majority of memory it is managing
decommitted.

The Backend glues together the various ranges to support the appropriate
way to manage memory on the platform.
2022-03-11 18:16:06 +00:00
David CARLIER
a602643fd2 g++ 12 unit test build fix. (#476)
test_random_allocation, g++ sees the removal from the list of the test case
as UAF.
2022-03-07 11:29:59 +00:00
David Chisnall
18ccfdecac Refactor memcpy to allow different versions. (#472)
Expose a memcpy.h that contains all of the bits of memcpy and clean up
the bounds checks header so that versions with both read and write
checks can coexist.
2022-03-04 13:33:11 +00:00
David Chisnall
95bd974fb0 Add test helper macros. (#465)
- Refactor the existing SNMALLOC_ASSERT and SNMALLOC_CHECK.  These now
   use the FatalErrorBuilder to format the output if a format string is
   provided.
 - Extend the FatalErrorBuilder to print decimal integers for signed
   values.
 - Rename FatalErrorBuilder to MessageBuilder.
 - Rewrite the macros used in the jemalloc tests to use
   FatalErrorBuilder and move them into a header.
 - Refactor some of the tests to use the new macros.
2022-02-25 15:57:28 +00:00
David Chisnall
93efbb4807 Refactor error reporting for bounds checks. (#464)
This introduces a very limited formatter that can embed strings and hex
representations of pointers / integers in an internal buffer. This is
used to format error strings for passing to `Pal::error`.  This is used,
in turn, by a wrapper for reporting bounds checks, which can be used by
external functions to implement bounds checks.

This removes the sprintf_l usage from the bounds checks.

This provides enough of a format implementation that the tests
introduced in #465 can be refactored to use this, instead of their
custom `printf` wrapper and that can be used by SNMALLOC_CHECK.  This
will be a follow-on PR.
2022-02-25 09:59:51 +00:00
Robert Norton
86aa28644c Errno fix (#463)
Correctly set errno on failure and improve the related test.

Previously the malloc test would emit an error message but not
abort if the errno was not as expected on failure. This
was because the return in the null == true case prevented the
check for failed == true at the end of check_result from
being reached. To resolve this just abort immediately as in the 
null case.

Also add tests of allocations that are expected to fail for
calloc and malloc.

To make the tests pass we need to set errno in several places,
making sure to keep this off the fast path.

We must also take care not to attempt to zero nullptr in case
of calloc failure.

See microsoft/snmalloc#461 and microsoft/snmalloc#463.
2022-02-24 10:09:29 +00:00
Robert Norton
af8ab2daf6 Clear freelist pointers on allocation for CHERI or CHECK_CLIENT builds.
This is especially important on CHERI to avoid leaking capabilities to
the freelist. In the CHERI case we also zero in clear_slab (see comment).
Also add a check in the malloc functional test that there are no valid
capabilities in the returned allocation.
2022-02-20 20:30:28 +00:00
David Chisnall
baf35cc80e Return a small allocation from realloc(ptr, 0). (#460)
An annoying amount of real-world code (e.g. mandoc, BSD sort) treats a
NULL return from `realloc` as a failure, even when requesting a size of
0.  This code is wrong (the standard explicitly permits a return of NULL
from realloc when given a size 0) but working around it in snmalloc is
easier than fixing it everywhere.
2022-02-11 15:11:15 +00:00
Matthew Parkinson
be98a27bf1 Improve RBTree
* Logging improvments
* No longer need for the representation to have a min and max.
2022-02-11 13:21:46 +00:00
Matthew Parkinson
79486b6331 Rearrange templates for buddy allocator. 2022-02-11 13:21:46 +00:00
David Chisnall
79ea08779b Add jemalloc compat functions. (#456)
This adds the full set of jemalloc functions that FreeBSD's libc
exposes, including some (the `*allocm` family) that are gone from newer
versions of jemalloc and the `*allocx` family that replaced them.  These
are not necessarily efficient implementations but they should allow
snmalloc to replace jemalloc without any ABI breakage (in the loosest
possible sense).

Jemalloc provides a very generic sysctl-like mechanism for setting and
getting some values.  These are all implemented to return the
not-supported error code.  This may break code that expects that they
will succeed.

In particular, these APIs are used to register custom backing-store
allocators and to manage caches and arenas.  These concepts don't map
directly onto snmalloc and attempting to do so would almost certainly
not provide the same performance characteristics and so it's better to
`LD_PRELOAD` jemalloc (or explicitly link to it) for programs that gain
a significant speedup from this.
2022-02-09 10:49:02 +00:00
Robert Norton
539937336d Extend malloc test to check CHERI capability length. 2022-02-08 14:17:43 +00:00
Matthew Parkinson
63d3928687 Add a red-black tree implementation and testing. 2022-02-01 17:18:36 +00:00
David Chisnall
f1be609cdb Small fixes for snmalloc used in FreeBSD libc. (#454)
- Mark the hook that we're exporting for the threading library to call
   to clean up per-thread malloc state as 'used'.  It was changed to
   `inline` to allow duplicate copies of it to be merged but this also
   means that it isn't emitted at all in compilation units that don't
   use it (and it isn't used internally at all).
 - Fix the `__je_bootstrap_*` functions, which are used to bootstrap TLS
   allocation, for the changes to `ScopedAllocator`.

The `__je_bootstrap*` functions weren't being built in CI.  They now are
for non-PIE targets with a smoke test.
2022-01-21 14:19:26 +00:00
Matthew Parkinson
61314f2260 Post large deallocations to original thread (#441)
* Post large deallocations to original thread

This change sets all large allocations to be owned by the originating
thread. This means they will be messaged back to the original thread
before they can be reused.

The following reason for making this change:
* This will improve producer/consumer apps involving large allocations.
* It enables the implementation of a more complex chunk allocator that
reassembles chunks.
* It addresses an issue with compartmentalisation where the handling of
large allocations can result in meta-data ownership changing.
2021-12-17 14:08:08 +00:00
David CARLIER
360efa2123 export netbsd's reallocarr proposal. (#433)
* export netbsd's reallocarr proposal.

acts subtly differently from reallocarray, returns an error code
and first argument as receiver.

* not export by default

* ci tests

* apply suggestions

* doc addition

* Apply suggestions from code review

Co-authored-by: Matthew Parkinson <mjp41@users.noreply.github.com>
2021-12-02 14:49:32 +00:00
Matthew Parkinson
7f3642e05c Change external thread_alloc example. (#424)
On Open Enclave having the `local_alloc` directly in thread-local
storage was causing a crash.  This changes the `local_alloc` to be
indirected, and thus puts less pressure on the thread-local storage.

The test also has deals with how to allocate before a thread-local
storage has been established.
2021-12-02 10:39:44 +00:00
David CARLIER
9332557bb0 memory unit test android build fix. (#427) 2021-11-24 12:12:47 +00:00
David CARLIER
e24130137d solaris systems build fix (#425) 2021-11-22 09:47:30 +00:00
Schrodinger ZHU Yifan
8e5514bd5a clean up unused usages (#421)
* clean up unused usages

Signed-off-by: SchrodingerZhu <i@zhuyi.fan>

* remove names for arg pack

Signed-off-by: SchrodingerZhu <i@zhuyi.fan>

* fix namespace in setup.h

Signed-off-by: SchrodingerZhu <i@zhuyi.fan>

* format

Signed-off-by: SchrodingerZhu <i@zhuyi.fan>

* set UNUSED as fast path

Signed-off-by: SchrodingerZhu <i@zhuyi.fan>
2021-11-19 13:23:39 +00:00
Matthew Parkinson
3d403aef7f Refactor use of sizeclasses (#415)
The primary aim for this refactor is to use a representation for
sizeclasses that uniformly covers both large and small.  This allows
certain operations such as alloc_size and external_pointer to be
uniformly implemented.

The additional types make clear which kind of sizeclass is in use.

This also tidies up the code for sizeclass based divisible by and
modulus.

It fixes a bug in rust_realloc that didn't correctly determine a realloc
was required for large classes.
2021-11-10 16:35:44 +00:00
Matthew Parkinson
02f36a4b31 Make test fail with more information. 2021-11-03 20:22:50 +00:00
Matthew Parkinson
19de27fdaf Improve fast path of handle remote deallocs
This adds some branch predictor and cache hints to the fast path of
processing remote deallocation. It also removes the batching.
2021-11-02 19:56:50 +00:00
Matthew Parkinson
5215bffa9e Change malloc test suite for errno
Errno is not required to be 0 on return from malloc,
so don't bother trying to make it 0. Leads to false test failures where
libc calls have not reset it after a failure.
2021-10-21 16:34:17 +01:00
Matthew Parkinson
4a7cd268f8 Rename slab_allocator to chunk_allocator 2021-10-20 18:38:08 +01:00
Nathaniel Wesley Filardo
31b8d99ca6 test/func/memcpy: adjust test sizes 2021-10-20 12:02:08 +01:00
Nathaniel Wesley Filardo
7f6378f5bf test/func/domestication: tweak for robustness
- Grab a larger second allocation on the first allocator to dodge the sizeclass
  of the prior alloc on that allocator *and* any implicit, bootstrapping slabs
  that get opened (e.g., for remote queue message stubs).

- De-FAST_PATH the domestication function.  No need to always inline it, here.

- Document things a little better
2021-10-20 12:02:08 +01:00
Nathaniel Wesley Filardo
1de28eead7 test/func/malloc fixes
- `check_result()` `abort()` on `null` and non-`nullptr` result.  Otherwise it
  just prints and doesn't end the test

- Don't call `realloc(, 0)`; this has never been consistent and the current C2x
  draft (see §7.22.3.5 and N2464) finally just declares it to be undefined
  behavior.  POSIX (2017) tolerates our current behavior of freeing the
  passed-in pointer and returning a new object.
2021-10-19 08:42:44 +01:00
Nathaniel Wesley Filardo
ed10717dde RemoteAllocator: dequeue as destructive iterator
This avoids repeated double-tapping domestication of the same pointer in
!QueueHeadsAreTame builds, by keeping the current "front" pointer to the queue
in trusted locations (stack, register) rather than storing it back to possibly
client-accessible memory.
2021-10-13 16:30:41 +01:00