Fortunately, C++ taketh away and C++ giveth, both, so here we are: a way to
detect if we're in the middle of definining a type that uses itself as a
template parameter in a way that flows into a concept check and, if so,
short-circuit out of the need to actually do any checks. Wonders never cease.
And do so by type, rather than by value. While here, introduce a C++20 concept
for this Backend-offered proxy and adjust the template parameters appropriately.
This will be useful for the process sandbox code, which needs to mediate stores
to the pagemap, but can provide a read-only view.
When we are accessing potentially out of range, then we might be
accessing before the pagemap has been initialised. Move the check
into the pagemap for better codegen.
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.
This passes though to an underlying allocator rather than using
snmalloc. This is required for using ASAN in Verona. Verona takes a
close coupling with snmalloc, but to use with ASAN would require a
more work, so we pass to the system allocator in this case.
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.
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>
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>
We mean to be allocating MIN_ALLOC_SIZE (== 2 * sizeof(void*)), not
sizeof(MIN_ALLOC_SIZE) (== sizeof(size_t)). This doesn't matter in practice
since, well, MIN_ALLOC_SIZE is the minimum allocation size, and so requesting
either will have the same effect. Still, best to say what we mean.
With snmalloc2, slabs are linked through the Metaslab structure directly rather
than in-band in a free allocation, so we no longer need to store a SlabLink in
even the smallest allocation classes.
The threshold for waking is used to ensure that we only use a slab when
it has sufficient space that we won't hit the slow path to soon after
using this slab. In the checked version, this is also used to give some
entropy in layout. Changing this to always be a pertcentage in the
checked case increases the effectiveness of the free list to detect OOB
write.
- 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`.
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.
Use a matrix containing objects rather than a matrix containing keys
that we try to use to define arrays of things.
Fix a typo in ARCH. Too much Arm made it AARCH.
Also add a check that the test programs are under about ten megabytes
(they're currently around one on platforms that put inline statics full
of zeroes into BSS and around 270 on ones that don't).
Fixes#339
The naming is more than a little confusing. AIUI, in Ubuntu's terminology, the
`powerpc` packages are for 32-bit machines, the `ppc64-powerpc` packages are for
Big Endian 64-bit machines, and the `ppc64el` packages are for Little Endian
64-bit machines.
Everyone seems to have agreed that the long-term answer for 64-bit PowerPC is
Little Endian (Debian maintains an unofficial BE port, but Canonical/Ubuntu,
RedHat, and SUSE all seem to have standardized on LE).
For maximal confusion, the appropriate triple's first component is, however,
`powerpc64le`.
The status badge should report the most recent status for the master
branch, not the most recent actions run.
llvm.sh wasn't updated when trunk moved to 14 so was failing to fetch clang-13 (which is now in the llvm-toolchain-focal-13 repo, not the llvm-toolchain-focal repo). Duplicate the correct logic here rather than relying on the external script.
A few highlights relative to our existing CI:
- Add a FreeBSD 12.2 and 13.0 runner so we have some FreeBSD CI.
- Windows builds use msbuild with the Visual-Studio-provided clang toolchain to test clang
- The matrix builds describe the axes of the matrix, not all points.
- The Arm builds now cross-compile with a native clang and run the tests with qemu, rather than running the compiler, linker, and ctest all with qemu.
This also includes a fix for one of the tests that was doing `static_cast<unsigned int>(1) << 36`, which is undefined behaviour and was sometimes causing qemu to hang. There is now an assert to catch this in the future.
This commit adds a simple XOR encoding to the next_object pointer in
FreeObjects. This removes the trivial way of getting hold of a physical
address from the system by observing the free list pointers in
deallocated objects.
* Make address space manager use pagemap for next pointers
The address space manager uses the pagemap entry to form linked lists of
unused address space above MIN_CHUNK_SIZE. It continues to use
references in the block below that threshold.
In the CHECK_CLIENT mode this makes it hard to corrupt the ASM as only
meta-data uses allocations below MIN_CHUNK_SIZE from the ASM. This
allocations will be protected with guard pages by the backend.
* address_space_core: use FreeChunk struct
Purely stylistic, NFCI. This hides some somewhat gnarly reinterpret_cast-s in
favor of more, but hopefully less gnarly, casts elsewhere.
* Apply suggestions from code review
Co-authored-by: Nathaniel Wesley Filardo <nfilardo@microsoft.com>
Take the maximum of...
* CACHELINE_SIZE (for performance)
* next_pow2(NUM_SIZECLASSES + 1) so that, when the pagemap points to a Remote,
the (small) size class stuffed in the bottom bits can be removed by alignment
* next_pow2(NUM_LARGE_CLASSES + 1) so that, when the pagemap isn't pointing to
a Remote, when the associated chunk is (part of) a large allocation, aligning
the Remote* results in 0.
The last of these conditions will almost never be the deciding factor, as there
are generally many more small size classes than large ones, but it shouldn't
hurt to be safe.