Commit Graph

10 Commits

Author SHA1 Message Date
Kostya Kortchinsky 2c56776a31 [scudo][standalone] Compact pointers for Caches/Batches
This CL introduces configuration options to allow pointers to be
compacted in the thread-specific caches and transfer batches. This
offers the possibility to have them use 32-bit of space instead of
64-bit for the 64-bit Primary, thus cutting the size of the caches
and batches by nearly half (and as such the memory used in size
class 0). The cost is an additional read from the region information
in the fast path.

This is not a new idea, as it's being used in the sanitizer_common
64-bit primary. The difference here is that it is configurable via
the allocator config, with the possibility of not compacting at all.

This CL enables compacting pointers in the Android and Fuchsia default
configurations.

Differential Revision: https://reviews.llvm.org/D96435
2021-02-25 12:14:38 -08:00
Peter Collingbourne 6dfe5801e0 scudo: Move the configuration for the primary allocator to Config. NFCI.
This will allow the primary and secondary allocators to share
the MaySupportMemoryTagging bool.

Differential Revision: https://reviews.llvm.org/D93728
2020-12-22 14:54:40 -08:00
Kostya Kortchinsky e456df77c2 [scudo][standalone] Fix Primary's ReleaseToOS test
Said test was flaking on Fuchsia for non-obvious reasons, and only
for ASan variants (the release was returning 0).

It turned out that the templating was off, `true` being promoted to
a `s32` and used as the minimum interval argument. This meant that in
some circumstances, the normal release would occur, and the forced
release would have nothing to release, hence the 0 byte released.

The symbols are giving it away (note the 1):
```
scudo::SizeClassAllocator64<scudo::FixedSizeClassMap<scudo::DefaultSizeClassConfig>,24ul,1,2147483647,false>::releaseToOS(void)
```

This also probably means that there was no MTE version of that test!

Differential Revision: https://reviews.llvm.org/D88457
2020-09-29 08:26:38 -07:00
Peter Collingbourne d876c7c8ec scudo: Remove the THREADLOCAL macro.
Replace all remaining uses with thread_local, which is a C++11
standard feature.

Differential Revision: https://reviews.llvm.org/D87478
2020-09-10 19:16:21 -07:00
Kostya Kortchinsky 6f00f3b56e [scudo][standalone] mallopt runtime configuration options
Summary:
Partners have requested the ability to configure more parts of Scudo
at runtime, notably the Secondary cache options (maximum number of
blocks cached, maximum size) as well as the TSD registry options
(the maximum number of TSDs in use).

This CL adds a few more Scudo specific `mallopt` parameters that are
passed down to the various subcomponents of the Combined allocator.

- `M_CACHE_COUNT_MAX`: sets the maximum number of Secondary cached items
- `M_CACHE_SIZE_MAX`: sets the maximum size of a cacheable item in the Secondary
- `M_TSDS_COUNT_MAX`: sets the maximum number of TSDs that can be used (Shared Registry only)

Regarding the TSDs maximum count, this is a one way option, only
allowing to increase the count.

In order to allow for this, I rearranged the code to have some `setOption`
member function to the relevant classes, using the `scudo::Option` class
enum to determine what is to be set.

This also fixes an issue where a static variable (`Ready`) was used in
templated functions without being set back to `false` every time.

Reviewers: pcc, eugenis, hctim, cferris

Subscribers: jfb, llvm-commits, #sanitizers

Tags: #sanitizers

Differential Revision: https://reviews.llvm.org/D84667
2020-07-28 11:57:54 -07:00
Peter Collingbourne c299d1981d scudo: Add initial memory tagging support.
When the hardware and operating system support the ARM Memory Tagging
Extension, tag primary allocation granules with a random tag. The granules
either side of the allocation are tagged with tag 0, which is normally
excluded from the set of tags that may be selected randomly. Memory is
also retagged with a random tag when it is freed, and we opportunistically
reuse the new tag when the block is reused to reduce overhead. This causes
linear buffer overflows to be caught deterministically and non-linear buffer
overflows and use-after-free to be caught probabilistically.

This feature is currently only enabled for the Android allocator
and depends on an experimental Linux kernel branch available here:
https://github.com/pcc/linux/tree/android-experimental-mte

All code that depends on the kernel branch is hidden behind a macro,
ANDROID_EXPERIMENTAL_MTE. This is the same macro that is used by the Android
platform and may only be defined in non-production configurations. When the
userspace interface is finalized the code will be updated to use the stable
interface and all #ifdef ANDROID_EXPERIMENTAL_MTE will be removed.

Differential Revision: https://reviews.llvm.org/D70762
2020-01-16 13:27:49 -08:00
Kostya Kortchinsky 0d3d4d3b0f [scudo][standalone] Make tests work on Fuchsia
Summary:
This CL makes unit tests compatible with Fuchsia's zxtest. This
required a few changes here and there, but also unearthed some
incompatibilities that had to be addressed.

A header is introduced to allow to account for the zxtest/gtest
differences, some `#if SCUDO_FUCHSIA` are used to disable incompatible
code (the 32-bit primary, or the exclusive TSD).

It also brought to my attention that I was using
`__scudo_default_options` in different tests, which ended up in a
single binary, and I am not sure how that ever worked. So move
this to the main cpp.

Additionally fully disable the secondary freelist on Fuchsia as we do
not track VMOs for secondary allocations, so no release possible.

With some modifications to Scudo's BUILD.gn in Fuchsia:
```
[==========] 79 tests from 23 test cases ran (10280 ms total).
[  PASSED  ] 79 tests
```

Reviewers: mcgrathr, phosek, hctim, pcc, eugenis, cferris

Subscribers: srhines, jfb, #sanitizers, llvm-commits

Tags: #sanitizers, #llvm

Differential Revision: https://reviews.llvm.org/D70682
2019-11-27 09:17:40 -08:00
Kostya Kortchinsky f7b1489ffc [scudo][standalone] Get statistics in a char buffer
Summary:
Following up on D68471, this CL introduces some `getStats` APIs to
gather statistics in char buffers (`ScopedString` really) instead of
printing them out right away. Ultimately `printStats` will just
output the buffer, but that allows us to potentially do some work
on the intermediate buffer, and can be used for a `mallocz` type
of functionality. This allows us to pretty much get rid of all the
`Printf` calls around, but I am keeping the function in for
debugging purposes.

This changes the existing tests to use the new APIs when required.

I will add new tests as suggested in D68471 in another CL.

Reviewers: morehouse, hctim, vitalybuka, eugenis, cferris

Reviewed By: morehouse

Subscribers: delcypher, #sanitizers, llvm-commits

Tags: #llvm, #sanitizers

Differential Revision: https://reviews.llvm.org/D68653

llvm-svn: 374173
2019-10-09 15:09:28 +00:00
Kostya Kortchinsky bebdab63e8 [scudo][standalone] Correct releaseToOS behavior
Summary:
There was an issue in `releaseToOSMaybe`: one of the criteria to
decide if we should proceed with the release was wrong. Namely:

```
const uptr N = Sci->Stats.PoppedBlocks - Sci->Stats.PushedBlocks;
if (N * BlockSize < PageSize)
  return; // No chance to release anything.
```

I meant to check if the amount of bytes in the free list was lower
than a page, but this actually checks if the amount of **in use** bytes
was lower than a page.

The correct code is:

```
const uptr BytesInFreeList =
  Region->AllocatedUser -
  (Region->Stats.PoppedBlocks - Region->Stats.PushedBlocks) * BlockSize;
if (BytesInFreeList < PageSize)
  return 0; // No chance to release anything.
```

Consequences of the bug:
- if a class size has less than a page worth of in-use bytes (allocated
  or in a cache), reclaiming would not occur, whatever the amount of
  blocks in the free list; in real world scenarios this is unlikely to
  happen and be impactful;
- if a class size had less than a page worth of free bytes (and enough
  in-use bytes, etc), then reclaiming would be attempted, with likely
  no result. This means the reclaiming was overzealous at times.

I didn't have a good way to test for this, so I changed the prototype
of the function to return the number of bytes released, allowing to
get the information needed. The test added fails with the initial
criteria.

Another issue is that `ReleaseToOsInterval` can actually be 0, meaning
we always try to release (side note: it's terrible for performances).
so change a `> 0` check to `>= 0`.

Additionally, decrease the `CanRelease` threshold to `PageSize / 32`.
I still have to make that configurable but I will do it at another time.

Finally, rename some variables in `printStats`: I feel like "available"
was too ambiguous, so change it to "total".

Reviewers: morehouse, hctim, eugenis, vitalybuka, cferris

Reviewed By: morehouse

Subscribers: delcypher, #sanitizers, llvm-commits

Tags: #llvm, #sanitizers

Differential Revision: https://reviews.llvm.org/D68471

llvm-svn: 373930
2019-10-07 17:37:39 +00:00
Nico Weber 3fa3831830 compiler-rt: Rename .cc file in lib/scudo/standalone/tests to .cpp
Like r367463, but for scudo/standalone/tests.

With this, all files in compiler-rt/lib have extension cpp.

llvm-svn: 367569
2019-08-01 14:38:49 +00:00