Commit Graph

715 Commits

Author SHA1 Message Date
Nathaniel Filardo
a9722667ab SP: add ArenaMap
The ArenaMap will store our internal provenance roots.  This commit simply
introduces the data structure and does not wire it up to the rest of the tree.
2021-04-09 12:39:29 +01:00
Nathaniel Filardo
d9822036b2 SP: add bounds placeholders to message queues
Like all the annotations so far, leave these as CBArena-bounded.

However, we can start to do a little better than we were doing before: for
not-large deallocations, we know that the internal superslab pointer is
sufficiently authoritative that we can use it to get to data structures rather
than also passing an amplified pointer to the allocation in question.  This,
then, partially reverts some of the earlier changes made while plumbing
CapPtr<>s through the system.

While here, avoid quite as many void*-s in favor of Remote* or SlabNext*.
2021-04-09 12:39:29 +01:00
Nathaniel Filardo
78ab0a7937 SP: external_pointer should not leak authority
Work with high-authority pointers internally, but then copy the address onto to
the low-authority pointer originally given to us (using the same primitive as
amplification, just backwards).  This ensures that clients cannot behave
non-monotonically even if they have access to external_pointer().  That is, we
are not an amplification oracle, though we might reveal the address of an object
somewhere clients cannot otherwise access.  Notably, we might reveal if a
{Super,Medium,}Slab has changed sizeclass (or been repurposed as or from a
Largealloc), forming a covert channel for data but not capabilities.  Of course,
if the pointer provided to external_alloc() is still useful, the implied UAF in
these scenarios is still its own problem.
2021-04-09 12:39:29 +01:00
Nathaniel Filardo
268ef2c059 SP: introduce AAL, PAL methods as per design doc
These capture the primitive architectural operations we are going to use.  At
the moment, since all AALs and PALs are not StrictProvenance, the only
implementations are stubs that just subvert the type system (but give us
something to compile against, going forward).
2021-04-09 12:39:29 +01:00
Nathaniel Filardo
c5aff8ed74 SP: plumb CapPtr through cache_friendly functions
Change these functions from being void* to void* to either consuming or
producing FreeObject*-s as appropriate.
2021-04-09 12:39:29 +01:00
Nathaniel Filardo
97f508e2b3 SP: further CapPtr plumbing 2021-04-09 12:39:29 +01:00
Nathaniel Filardo
3541a0cfe1 SP: Allocator::large_alloc return CapPtr<>
Document and suppress MSVC's confusion with CapPtr<>'s constructor (the
suppression has to happen at the definition, not the use, of the constructor) in
the case of never-needs-initialization Allocator-s.
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
Nathaniel Filardo
313a682faf SP: capptr_bound_chunkd, capptr_chunk_from_chunkd
These helpers centralize the handling of CBChunkD-related flows
2021-04-09 12:39:29 +01:00
Nathaniel Filardo
294887ad74 SP: introduce CapPtr<> wrapper type & bounds taxonomy
This commit just fills out ds/ptrwrap.h with the new types and adds utility
methods to ds/address.h.
2021-04-09 12:39:29 +01:00
Nathaniel Filardo
c6036f3808 Add StrictProvenance (SP) design document 2021-04-09 12:39:29 +01:00
Nathaniel Filardo
cfa996692f Correct PAL Concept
The test for NoAllocation/AlignedAllocation/neither was broken and this was
undetected until the sandbox demo came into being with its NoAllocation PAL
instance.  (Sadly, this remained undetected for so long because we can't
routinely build with C++20 because std::atomic_t<>'s initialization rules
changed in ways that make us require oodles and oodles of RAM at compile time.
This patch has been validated with -j1 on a machine with lots of RAM.)

Separately, it's possible that we end up here without `using namespace std`,
which seems like overkill.  So just use `std::size_t` ourselves within the PAL
Concept definition.
2021-04-07 18:06:18 +01:00
Matthew Parkinson
d1acb7979a Improve codegen for start of object.
By doubling the mod_mult array, we cause the division part of the
calculation to completely overflow, and thus remove one instruction from
fast path.
2021-04-07 11:43:53 +01:00
Matthew Parkinson
9ca73b8153 Implementing full permutation of slab
Allocate slab is randomly in all possible permutations. This increases
the entropy of the order considerably.  This uses an algorithm to build
a random cycle in a slab, and then use this to build the free list.

We disable the per-slab randomisation in the non-CHECK_CLIENT builds.
2021-04-07 11:43:53 +01:00
Matthew Parkinson
7202f9e091 Handle UB that was not exercised originally. 2021-04-07 11:43:53 +01:00
Nathaniel Filardo
ebe8489910 Size-known large dealloc paths should also round up
Like we already do in the size-unknown case.  This ensures that in the CHERI
case we'll always bound to the size of the segment we return to the large alloc,
not to a subset.  It has the added bonus of ensuring that our bounds are
precisely representable.
2021-04-06 16:25:57 +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
Nathaniel Filardo
7f841ff081 NFC: Introduce and switch to pal_zero
This wrapper will allow us to pass `AuthPtr<T,B> p` to zero() without needing to
write `p.unsafe_auth_ptr` to get to a `T*` inside.  Moreover, it will give us a
convenient point to assert that `B` is such that the pointer can be used to
manipulate the memory map (i.e. is not exported).
2021-04-06 16:25:57 +01:00
Nathaniel Filardo
4cfcf344fc NFC: LargeAlloc::alloc() take rsize and size both
Mostly for similarity with mediumslabs.  Might shave off a few instructions on
some rare paths (when we know that size == rsize == SUPERSLAB_SIZE).
2021-04-06 16:25:57 +01:00
Nathaniel Filardo
c94e37f5fc alloc: pass rsize, not size, down to Mediumslab::alloc
When we get to CHERI, sizes derived from sizeclasses are always precisely
representable, while other sizes may not be.

This should induce no change in behavior without CHERI, except that we might
PAL::zero slightly more memory this way.
2021-04-06 16:25:57 +01:00
Nathaniel Filardo
a1f17e6060 Mediumslab: pre-factor init() to take explicit self 2021-04-06 16:25:57 +01:00
Nathaniel Filardo
d1b2522a10 Remove stale get_slab
Everything seems to be using the `Metaslab::get_slab` form instead
2021-04-06 16:25:57 +01:00
Nathaniel Filardo
88150b497f NFC: style-correct allocslab #include 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
0377fd88d4 Improve BSDs support. 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
cc5f1cfe9f Expose entropy on POSIX platforms
This provides a common definition for many POSIX platforms. It
can be disabled.
2021-04-06 14:09:18 +01:00
Matthew Parkinson
6daa261161 Expose Entropy on Windows 2021-04-06 14:09:18 +01:00
Matthew Parkinson
f15dc6ee2e Expose Entropy
Define various parts of random that can be used to make the layout of
memory more random.  Thread this through the allocator.

Expose the concept as part of the Pal. Subsequent commits will expose
that on different platforms.
2021-04-06 14:09:18 +01:00
Nathaniel Filardo
c5b65d07b8 FreeObject: hide harder from the compiler, tweak types
On CHERI, the compiler will always issue a warning for
`reinterpret_cast<T*>(ptraddr_t)` and similar expressions, and of course, if the
compiler can see far enough into the types, the presence of `if constexpr` will
not save us.  Therefore, lift the conditional out to two definitions of
`FreeObject::encode` using `std::enable_if_t` to gate which is used.
2021-03-26 11:43:06 +00:00
Matthew Parkinson
afc6283e01 Threshold freelist wakeup
When a slab has been fully allocated, then we no longer
check it has entries until something returns an allocation to this slab.
However, it is possible that only a single allocation is available, and
then we can end up frequently on the slow path.

This change only considers free lists that cover at least 1/8 of a slab.
This means that we will hit the slow path less frequently.  This also
means that the randomisation changes will have more entropy: with a
single element free list there is only one order.

For large small sizes it can still be a single element, as 1/8 is of the
slab capacity is below 1. We max out the trigger at 31 elements to
reduce unneeded wasted space.
2021-03-25 12:04:36 +00:00
Matthew Parkinson
578abd8db4 Randomise slab allocation pattern (#304)
The slab allocation pattern is randomised based on the deallocation
pattern.  This achieved by using two queues to enqueue free elements
onto.  We pick "randomly", which queue to add to, and then when we take
the free_queue to use, we splice the two queues together.
2021-03-24 16:12:22 +00:00
Nathaniel Filardo
6442f4edd8 NFC: make Superslab interfaces static
As with 4f6cf8cb40, this will let us annotate
the explicit pointers
2021-03-24 11:55:05 +00:00
Nathaniel Filardo
e5a94ed902 NFC: constexpr some subexpressions in ds/bits
MSVC throws warnings for things that could be but aren't constexpr.
2021-03-24 11:55:05 +00: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
04a185e634 Remove allocated field from Metaslab
The metaslab contains a field specifying how many elements have been
allocated.  As the code has evolved this field has now always become
the maximum capacity of the slab for the sizeclass.

This commit looks up this value based on the sizeclass, and removes the
field from the slab's metadata.
2021-03-22 13:07:57 +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
ca1540c0d9 Remove allow_reserve feature
This was original designed for Project Snowflake to enable a careful
interoperation between an allocator and the thread suspend behaviour in
.NET.

This feature is not being tested or used by any current project.  This
form of interop would be better served by designing a special Pal to
interop with the CLR if this is ever needed.

This commit removes the feature.
2021-03-21 19:00:54 +00:00
Matthew Parkinson
fd7b040823 Align wrapper for array. 2021-03-19 20:11:15 +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
486ef10c21 NFC: bump pointers have just one associated Slab
Rather than ::get()-ing the `Superslab` and `Slab` for each object we just
created from the bump pointer, recognize that these objects necessarily come
from the same `Slab` (and so the same `Superslab`).  In the eventuality of
CHERI, this means we'll amplify once per bump pointer, not once per created
object.
2021-03-19 15:17:56 +00:00
Nathaniel Filardo
1549e40705 NFC: cdllist: some residual pointer wrapper violence
Missed this the last time around
2021-03-19 15:17:56 +00:00
Nathaniel Filardo
c5e08573bf NFC: prepare RemoteCache API for amplification
When post()-ing the RemoteCache to message queues, we push an entire bucket
onto a remote allocator's incoming queue (specifically, the allocator owning
the front Remote in the bucket we're moving).  In order to do that, we need to
exceed the bounds of the Remote allocation and reference its Allocslab header
(to get the ->message_queue).  On StrictProvenance architectures, this will
require that we amplify the head Remote* and then engage in some pointer math.

While Remotes contain the address of the message_queue as the allocator's
identity, this may not be a pointer, just an address, and may have undergone
obfuscation anyway.
2021-03-19 15:17:56 +00:00
Nathaniel Filardo
5938f0b5a6 NFC: add align_{down,up}<size_t>(address_t) 2021-03-19 15:17:56 +00:00
Nathaniel Filardo
ebc02a141e NFC: MPMCStack: prepare for pointer wrappers 2021-03-19 15:17:56 +00:00
Matthew Parkinson
ed615eade9 Refactor checks to improve codegen. 2021-03-19 11:28:39 +00:00
Matthew Parkinson
0983f1837b Alternate allocation pattern 2021-03-19 11:28:39 +00:00
Matthew Parkinson
50f412157f Protect free list pointers stored in object space
Free list pointers can be exploited by attackers. This commit implements
a simple encoding scheme to detect corruption of the pointers.  This can
be used to detect UAF and double free.

This does not currently address anything for Medium or Large
allocations.  It also does not address cross thread deallocations.

Co-authored-by: Nathaniel Wesley Filardo <nfilardo@microsoft.com>
2021-03-19 11:28:39 +00:00