Commit Graph

70 Commits

Author SHA1 Message Date
Peter Collingbourne 9c86b83ffc scudo: Replace ALIGNED macro with standard alignas specifier.
alignas was introduced in C++11 and is already being used throughout LLVM.

Differential Revision: https://reviews.llvm.org/D77823
2020-04-09 14:36:03 -07:00
Peter Collingbourne 8140f6bcde scudo: Create a public include directory. NFCI.
For MTE error reporting we will need to expose interfaces for crash handlers
to use to interpret scudo headers and metadata. The intent is that these
interfaces will live in scudo/interface.h.

Move the existing interface.h into an include/scudo directory and make it
independent of the internal headers, so that we will be able to add the
interfaces there.

Differential Revision: https://reviews.llvm.org/D76648
2020-03-23 18:23:29 -07:00
Kostya Kortchinsky f8352502a3 [scudo][standalone] Allow fallback to secondary if primary is full
Summary:
We introduced a way to fallback to the immediately larger size class for
the Primary in the event a region was full, but in the event of the largest
size class, we would just fail.

This change allows to fallback to the Secondary when the last region of
the Primary is full. We also expand the trick to all platforms as opposed
to being Android only, and update the test to cover the new case.

Reviewers: hctim, cferris, eugenis, morehouse, pcc

Subscribers: #sanitizers, llvm-commits

Tags: #sanitizers

Differential Revision: https://reviews.llvm.org/D76430
2020-03-20 07:55:20 -07:00
Kostya Kortchinsky c753a306fd [scudo][standalone] Various improvements wrt RSS
Summary:
This patch includes several changes to reduce the overall footprint
of the allocator:
- for realloc'd chunks: only keep the same chunk when lowering the size
  if the delta is within a page worth of bytes;
- when draining a cache: drain the beginning, not the end; we add pointers
  at the end, so that meant we were draining the most recently added
  pointers;
- change the release code to account for an freed up last page: when
  scanning the pages, we were looking for pages fully covered by blocks;
  in the event of the last page, if it's only partially covered, we
  wouldn't mark it as releasable - even what follows the last chunk is
  all 0s. So now mark the rest of the page as releasable, and adapt the
  test;
- add a missing `setReleaseToOsIntervalMs` to the cacheless secondary;
- adjust the Android classes based on more captures thanks to pcc@'s
  tool.

Reviewers: pcc, cferris, hctim, eugenis

Subscribers: #sanitizers, llvm-commits

Tags: #sanitizers, #llvm

Differential Revision: https://reviews.llvm.org/D75142
2020-02-26 12:25:43 -08:00
Kostya Kortchinsky 21695710cf [scudo][standalone] Workaround for full regions on Android
Summary:
Due to Unity, we had to reduce our region sizes, but in some rare
situations, some programs (mostly tests AFAICT) manage to fill up
a region for a given size class.

So this adds a workaround for that attempts to allocate the block
from the immediately larger size class, wasting some memory but
allowing the application to keep going.

Reviewers: pcc, eugenis, cferris, hctim, morehouse

Subscribers: #sanitizers, llvm-commits

Tags: #sanitizers, #llvm

Differential Revision: https://reviews.llvm.org/D74567
2020-02-13 12:54:25 -08:00
Peter Collingbourne 87303fd917 scudo: Fix various test failures, mostly on 32-bit.
Differential Revision: https://reviews.llvm.org/D74429
2020-02-11 12:18:35 -08:00
Peter Collingbourne 9068766b9a scudo: Add a dump of primary allocation sizes to malloc_info output.
This will be useful for optimizing the size class map.

Differential Revision: https://reviews.llvm.org/D74098
2020-02-10 15:05:27 -08:00
Peter Collingbourne 041547eb4e scudo: Table driven size classes for Android allocator.
Add an optional table lookup after the existing logarithm computation
for MidSize < Size <= MaxSize during size -> class lookups. The lookup is
O(1) due to indexing a precomputed (via constexpr) table based on a size
table. Switch to this approach for the Android size class maps.

Other approaches considered:
- Binary search was found to have an unacceptable (~30%) performance cost.
- An approach using NEON instructions (see older version of D73824) was found
  to be slightly slower than this approach on newer SoCs but significantly
  slower on older ones.

By selecting the values in the size tables to minimize wastage (for example,
by passing the malloc_info output of a target program to the included
compute_size_class_config program), we can increase the density of allocations
at a small (~0.5% on bionic malloc_sql_trace as measured using an identity
table) performance cost.

Reduces RSS on specific Android processes as follows (KB):

                             Before  After
zygote (median of 50 runs)    26836  26792 (-0.2%)
zygote64 (median of 50 runs)  30384  30076 (-1.0%)
dex2oat (median of 3 runs)   375792 372952 (-0.8%)

I also measured the amount of whole-system idle dirty heap on Android by
rebooting the system and then running the following script repeatedly until
the results were stable:

for i in $(seq 1 50); do grep -A5 scudo: /proc/*/smaps | grep Pss: | cut -d: -f2 | awk '{s+=$1} END {print s}' ; sleep 1; done

I did this 3 times both before and after this change and the results were:

Before: 365650, 356795, 372663
After:  344521, 356328, 342589

These results are noisy so it is hard to make a definite conclusion, but
there does appear to be a significant effect.

On other platforms, increase the sizes of all size classes by a fixed offset
equal to the size of the allocation header. This has also been found to improve
density, since it is likely for allocation sizes to be a power of 2, which
would otherwise waste space by pushing the allocation into the next size class.

Differential Revision: https://reviews.llvm.org/D73824
2020-02-10 14:59:49 -08:00
Peter Collingbourne dab7bdad04 scudo: Delete unused class ScudoByteMap. NFCI.
The class is only used in SizeClassAllocator32 in 64-bit mode, but we don't
use that class in 64-bit mode.

Differential Revision: https://reviews.llvm.org/D74099
2020-02-06 09:30:24 -08:00
Mitch Phillips a62586846f [GWP-ASan] Crash Handler API.
Summary:
Forewarning: This patch looks big in #LOC changed. I promise it's not that bad, it just moves a lot of content from one file to another. I've gone ahead and left inline comments on Phabricator for sections where this has happened.

This patch:
 1. Introduces the crash handler API (crash_handler_api.h).
 2. Moves information required for out-of-process crash handling into an AllocatorState. This is a trivially-copied POD struct that designed to be recovered from a deceased process, and used by the crash handler to create a GWP-ASan report (along with the other trivially-copied Metadata struct).
 3. Implements the crash handler API using the AllocatorState and Metadata.
 4. Adds tests for the crash handler.
 5. Reimplements the (now optionally linked by the supporting allocator) in-process crash handler (i.e. the segv handler) using the new crash handler API.
 6. Minor updates Scudo & Scudo Standalone to fix compatibility.
 7. Changed capitalisation of errors (e.g. /s/Use after free/Use After Free).

Reviewers: cryptoad, eugenis, jfb

Reviewed By: eugenis

Subscribers: merge_guards_bot, pcc, jfb, dexonsmith, mgorny, cryptoad, #sanitizers, llvm-commits

Tags: #sanitizers, #llvm

Differential Revision: https://reviews.llvm.org/D73557
2020-02-05 15:39:17 -08:00
Kostya Kortchinsky a9d5f8989d [scudo][standalone] Fix a race in the secondary release
Summary:
I tried to move the `madvise` calls outside of one of the secondary
mutexes, but this backfired. There is situation when a low release
interval is set combined with secondary pressure that leads to a race:
a thread can get a block from the cache, while another thread is
`madvise`'ing that block, resulting in a null header.

I changed the secondary race test so that this situation would be
triggered, and moved the release into the cache mutex scope.

Reviewers: cferris, pcc, eugenis, hctim, morehouse

Subscribers: jfb, #sanitizers, llvm-commits

Tags: #sanitizers, #llvm

Differential Revision: https://reviews.llvm.org/D74072
2020-02-05 11:02:51 -08:00
Kostya Kortchinsky 993e3c9269 [scudo][standalone] Secondary & general other improvements
Summary:
This CL changes multiple things to improve performance (notably on
Android).We introduce a cache class for the Secondary that is taking
care of this mechanism now.

The changes:
- change the Secondary "freelist" to an array. By keeping free secondary
  blocks linked together through their headers, we were keeping a page
  per block, which isn't great. Also we know touch less pages when
  walking the new "freelist".
- fix an issue with the freelist getting full: if the pattern is an ever
  increasing size malloc then free, the freelist would fill up and
  entries would not be used. So now we empty the list if we get to many
  "full" events;
- use the global release to os interval option for the secondary: it
  was too costly to release all the time, particularly for pattern that
  are malloc(X)/free(X)/malloc(X). Now the release will only occur
  after the selected interval, when going through the deallocate path;
- allow release of the `BatchClassId` class: it is releasable, we just
  have to make sure we don't mark the batches containing batches
  pointers as free.
- change the default release interval to 1s for Android to match the
  current Bionic allocator configuration. A patch is coming up to allow
  changing it through `mallopt`.
- lower the smallest class that can be released to `PageSize/64`.

Reviewers: cferris, pcc, eugenis, morehouse, hctim

Subscribers: phosek, #sanitizers, llvm-commits

Tags: #sanitizers, #llvm

Differential Revision: https://reviews.llvm.org/D73507
2020-01-28 07:28:55 -08:00
Evgenii Stepanov 596d06145a [GWP-ASan] enable/disable and fork support.
Summary:
* Implement enable() and disable() in GWP-ASan.
* Setup atfork handler.
* Improve test harness sanity and re-enable GWP-ASan in Scudo.

Scudo_standalone disables embedded GWP-ASan as necessary around fork().
Standalone GWP-ASan sets the atfork handler in init() if asked to. This
requires a working malloc(), therefore GWP-ASan initialization in Scudo
is delayed to the post-init callback.

Test harness changes are about setting up a single global instance of
the GWP-ASan allocator so that pthread_atfork() does not create
dangling pointers.

Test case shamelessly stolen from D72470.

Reviewers: cryptoad, hctim, jfb

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

Tags: #sanitizers, #llvm

Differential Revision: https://reviews.llvm.org/D73294
2020-01-24 13:53:26 -08: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 9ef6faf496 [scudo][standalone] Fork support
Summary:
fork() wasn't well (or at all) supported in Scudo. This materialized
in deadlocks in children.

In order to properly support fork, we will lock the allocator pre-fork
and unlock it post-fork in parent and child. This is done via a
`pthread_atfork` call installing the necessary handlers.

A couple of things suck here: this function allocates - so this has to
be done post initialization as our init path is not reentrance, and it
doesn't allow for an extra pointer - so we can't pass the allocator we
are currently working with.

In order to work around this, I added a post-init template parameter
that gets executed once the allocator is initialized for the current
thread. Its job for the C wrappers is to install the atfork handlers.

I reorganized a bit the impacted area and added some tests, courtesy
of cferris@ that were deadlocking prior to this fix.

Subscribers: jfb, #sanitizers, llvm-commits

Tags: #sanitizers, #llvm

Differential Revision: https://reviews.llvm.org/D72470
2020-01-14 07:51:48 -08:00
Kostya Kortchinsky 77e906ac78 [scudo][standalone] Implement TSD registry disabling
Summary:
In order to implement `malloc_{enable|disable}` we were just disabling
(or really locking) the Primary and the Secondary. That meant that
allocations could still be serviced from the TSD as long as the cache
wouldn't have to be filled from the Primary.

This wasn't working out for Android tests, so this change implements
registry disabling (eg: locking) so that `getTSDAndLock` doesn't
return a TSD if the allocator is disabled. This also means that the
Primary doesn't have to be disabled in this situation.

For the Shared Registry, we loop through all the TSDs and lock them.
For the Exclusive Registry, we add a `Disabled` boolean to the Registry
that forces `getTSDAndLock` to use the Fallback TSD instead of the
thread local one. Disabling the Registry is then done by locking the
Fallback TSD and setting the boolean in question (I don't think this
needed an atomic variable but I might be wrong).

I clang-formatted the whole thing as usual hence the couple of extra
whiteline changes in this CL.

Reviewers: cferris, pcc, hctim, morehouse, eugenis

Subscribers: jfb, #sanitizers, llvm-commits

Tags: #sanitizers, #llvm

Differential Revision: https://reviews.llvm.org/D71719
2019-12-20 06:52:13 -08:00
Mitch Phillips a00cd6dfea [GWP-ASan] [Scudo] ifdef entire GWP-ASan tests.
Turns out that gtest in LLVM is only 1.8.0 (the newest version 1.10.0)
supports the GTEST_SKIP() macro, and apparently I didn't build w/o
GWP-ASan.

Should fix the GN bot, as well as any bots that may spuriously break on
platforms where the code wasn't correctly ifdef'd out as well.
2019-12-13 09:45:28 -08:00
Mitch Phillips ed4618edb3 [Scudo] [GWP-ASan] Add GWP-ASan to Scudo Standalone.
Summary:
Adds GWP-ASan to Scudo standalone. Default parameters are pulled across from the
GWP-ASan build. No backtrace support as of yet.

Reviewers: cryptoad, eugenis, pcc

Reviewed By: cryptoad

Subscribers: merge_guards_bot, mgorny, #sanitizers, llvm-commits, cferris, vlad.tsyrklevich, pcc

Tags: #sanitizers, #llvm

Differential Revision: https://reviews.llvm.org/D71229
2019-12-13 09:09:41 -08:00
Peter Collingbourne c8a2882a97 scudo: Fix one of the C wrapper tests on Android.
The test ScudoWrappersCTest.Realloc expects realloc of memalign to work on
Android, but this relies on dealloc_type_mismatch being set to false. Commit
0d3d4d3b0 caused us to start setting it to true in the C wrapper tests,
which broke the test. Set it to the correct value on Android.

Differential Revision: https://reviews.llvm.org/D71078
2019-12-05 11:15:31 -08:00
Peter Collingbourne 0cfe0a7bb0 scudo: Fix the build of wrappers_c_test.cpp on Android.
The Android headers don't provide a declaration of valloc or pvalloc, so we
need to declare them ourselves.

Differential Revision: https://reviews.llvm.org/D71077
2019-12-05 11:15:00 -08:00
Kostya Kortchinsky 5595249e48 [scudo][standalone] Add chunk ownership function
Summary:
In order to be compliant with tcmalloc's extension ownership
determination function, we have to expose a function that will
say if a chunk was allocated by us.

As to whether or not this has security consequences: someone
able to call this function repeatedly could use it to determine
secrets (cookie) or craft a valid header. So this should not be
exposed directly to untrusted user input.

Add related tests.

Additionally clang-format caught a few things to change.

Reviewers: hctim, pcc, cferris, eugenis, vitalybuka

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

Tags: #sanitizers, #llvm

Differential Revision: https://reviews.llvm.org/D70908
2019-12-03 08:32:26 -08:00
Peter Collingbourne b208088a21 scudo: Limit the number of bytes tested in a realloc test.
This test was previously effectively doing:
P = malloc(X); write X bytes to P; P = realloc(P, X - Y); P = realloc(P, X)
and expecting that all X bytes stored to P would still be identical after
the final realloc.

This happens to be true for the current scudo implementation of realloc,
but is not guaranteed to be true by the C standard ("Any bytes in the new
object beyond the size of the old object have indeterminate values.").
This implementation detail will change with the new memory tagging support,
which unconditionally zeros newly allocated granules when memory tagging
is enabled. Fix this by limiting the number of bytes that we test to the
minimum size that we realloc the allocation to.

Differential Revision: https://reviews.llvm.org/D70761
2019-11-27 10:32:34 -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 15664fe2c4 [scudo][standalone] Fix for releaseToOS prior to init
Summary:
cferris@ found an issue where calling `releaseToOS` prior to any other
heap operation would lead to a crash, due to the allocator not being
properly initialized (it was discovered via `mallopt`).

The fix is to call `initThreadMaybe` prior to calling `releaseToOS` for
the Primary.

Add a test that crashes prior to fix.

Reviewers: hctim, cferris, pcc, eugenis

Subscribers: #sanitizers, llvm-commits

Tags: #sanitizers, #llvm

Differential Revision: https://reviews.llvm.org/D70552
2019-11-25 08:38:45 -08:00
Peter Collingbourne f751a79173 scudo: Only use the Android reserved TLS slot when building libc's copy of the allocator.
When we're not building libc's allocator, just use a regular TLS variable. This
lets the unit tests pass on Android devices whose libc uses Scudo. Otherwise
libc's copy of Scudo and the unit tests' copy will both try to use the same
TLS slot, in likely incompatible ways.

This requires using ELF TLS, so start passing -fno-emulated-tls when building
the library and the unit tests on Android.

Differential Revision: https://reviews.llvm.org/D70472
2019-11-20 11:30:58 -08:00
Peter Collingbourne 10089ce202 scudo: Switch from std::random_shuffle to std::shuffle in a test.
This lets the test build with C++17.

Differential Revision: https://reviews.llvm.org/D70471
2019-11-19 16:13:12 -08:00
Kostya Kortchinsky f018246c20 [scudo][standalone] Enabled SCUDO_DEBUG for tests + fixes
Summary:
`SCUDO_DEBUG` was not enabled for unit tests, meaning the `DCHECK`s
were never tripped. While turning this on, I discovered that a few
of those not-exercised checks were actually wrong. This CL addresses
those incorrect checks.

Not that to work in tests `CHECK_IMPL` has to explicitely use the
`scudo` namespace. Also changes a C cast to a C++ cast.

Reviewers: hctim, pcc, cferris, eugenis, vitalybuka

Subscribers: mgorny, #sanitizers, llvm-commits

Tags: #sanitizers, #llvm

Differential Revision: https://reviews.llvm.org/D70276
2019-11-15 08:33:57 -08:00
Kostya Kortchinsky c7bc3db23c [scudo][standalone] Fix Secondary bug w/ freelist
Summary:
cferris@ found an issue due to the new Secondary free list behavior
and unfortunately it's completely my fault. The issue is twofold:

- I lost track of the (major) fact that the Combined assumes that
  all chunks returned by the Secondary are zero'd out apprioriately
  when dealing with `ZeroContents`. With the introduction of the
  freelist, it's no longer the case as there can be a small portion
  of memory between the header and the next page boundary that is
  left untouched (the rest is zero'd via release). So the next time
  that block is returned, it's not fully zero'd out.
- There was no test that would exercise that behavior :(

There are several ways to fix this, the one I chose makes the most
sense to me: we pass `ZeroContents` to the Secondary's `allocate`
and it zero's out the block if requested and it's coming from the
freelist. The prevents an extraneous `memset` in case the block
comes from `map`. Another possbility could have been to `memset`
in `deallocate`, but it's probably overzealous as all secondary
blocks don't need to be zero'd out.

Add a test that would have found the issue prior to fix.

Reviewers: morehouse, hctim, cferris, pcc, eugenis, vitalybuka

Subscribers: #sanitizers, llvm-commits

Tags: #sanitizers, #llvm

Differential Revision: https://reviews.llvm.org/D69675
2019-10-31 14:38:30 -07:00
Kostya Kortchinsky 19ea1d46cc [scudo][standalone] Add a free list to the Secondary
Summary:
The secondary allocator is slow, because we map and unmap each block
on allocation and deallocation.

While I really like the security benefits of such a behavior, this
yields very disappointing performance numbers on Android for larger
allocation benchmarks.

So this change adds a free list to the secondary, that will hold
recently deallocated chunks, and (currently) release the extraneous
memory. This allows to save on some memory mapping operations on
allocation and deallocation. I do not think that this lowers the
security of the secondary, but can increase the memory footprint a
little bit (RSS & VA).

The maximum number of blocks the free list can hold is templatable,
`0U` meaning that we fallback to the old behavior. The higher that
number, the higher the extra memory footprint.

I added default configurations for all our platforms, but they are
likely to change in the near future based on needs and feedback.

Reviewers: hctim, morehouse, cferris, pcc, eugenis, vitalybuka

Subscribers: mgorny, #sanitizers, llvm-commits

Tags: #sanitizers, #llvm

Differential Revision: https://reviews.llvm.org/D69570
2019-10-30 08:55:58 -07:00
Kostya Kortchinsky 2513250be3 [scudo][standalone] Lists fix
Summary:
Apparently during the review of D69265, and my flailing around with
git, a somewhat important line disappeared.

On top of that, there was no test exercising that code path, and
while writing the follow up patch I intended to write, some `CHECK`s
were failing.

Re-add the missing line, and add a test that fails without said line.

Reviewers: hctim, morehouse, pcc, cferris

Reviewed By: hctim

Subscribers: #sanitizers, llvm-commits

Tags: #sanitizers, #llvm

Differential Revision: https://reviews.llvm.org/D69529
2019-10-28 15:08:08 -07:00
Kostya Kortchinsky 6f2de9cbb3 [scudo][standalone] Consolidate lists
Summary:
This is a clean patch using the last diff of D69265, but using git
instead of svn, since svn went ro and arc was making my life harded
than it needed to be.

I was going to introduce a couple more lists and realized that our
lists are currently a bit all over the place. While we have a singly
linked list type relatively well defined, we are using doubly linked
lists defined on the fly for the stats and for the secondary blocks.

This CL adds a doubly linked list object, reorganizing the singly list
one to extract as much of the common code as possible. We use this
new type in the stats and the secondary. We also reorganize the list
tests to benefit from this consolidation.

There are a few side effect changes such as using for iterator loops
that are, in my opinion, cleaner in a couple of places.

Reviewers: hctim, morehouse, pcc, cferris

Reviewed By: hctim

Subscribers: jfb, #sanitizers, llvm-commits

Tags: #sanitizers, #llvm

Differential Revision: https://reviews.llvm.org/D69516
2019-10-28 09:34:36 -07: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
Kostya Kortchinsky dc802dbef2 [scudo][standalone] Make malloc_info return a minimal XML
Summary:
Initially, our malloc_info was returning ENOTSUP, but Android would
rather have it return successfully and write a barebone XML to the
stream, so we will oblige.

Add an associated test.

Reviewers: cferris, morehouse, hctim, eugenis, vitalybuka

Reviewed By: morehouse

Subscribers: delcypher, #sanitizers, llvm-commits

Tags: #llvm, #sanitizers

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

llvm-svn: 373754
2019-10-04 15:46:34 +00:00
Kostya Kortchinsky 161cca266a [scudo][standalone] Android related improvements
Summary:
This changes a few things to improve memory footprint and performances
on Android, and fixes a test compilation error:
- add `stdlib.h` to `wrappers_c_test.cc` to address
  https://bugs.llvm.org/show_bug.cgi?id=42810
- change Android size class maps, based on benchmarks, to improve
  performances and lower the Svelte memory footprint. Also change the
  32-bit region size for said configuration
- change the `reallocate` logic to reallocate in place for sizes larger
  than the original chunk size, when they still fit in the same block.
  This addresses patterns from `memory_replay` dumps like the following:
```
202: realloc 0xb48fd000 0xb4930650 12352
202: realloc 0xb48fd000 0xb48fd000 12420
202: realloc 0xb48fd000 0xb48fd000 12492
202: realloc 0xb48fd000 0xb48fd000 12564
202: realloc 0xb48fd000 0xb48fd000 12636
202: realloc 0xb48fd000 0xb48fd000 12708
202: realloc 0xb48fd000 0xb48fd000 12780
202: realloc 0xb48fd000 0xb48fd000 12852
202: realloc 0xb48fd000 0xb48fd000 12924
202: realloc 0xb48fd000 0xb48fd000 12996
202: realloc 0xb48fd000 0xb48fd000 13068
202: realloc 0xb48fd000 0xb48fd000 13140
202: realloc 0xb48fd000 0xb48fd000 13212
202: realloc 0xb48fd000 0xb48fd000 13284
202: realloc 0xb48fd000 0xb48fd000 13356
202: realloc 0xb48fd000 0xb48fd000 13428
202: realloc 0xb48fd000 0xb48fd000 13500
202: realloc 0xb48fd000 0xb48fd000 13572
202: realloc 0xb48fd000 0xb48fd000 13644
202: realloc 0xb48fd000 0xb48fd000 13716
202: realloc 0xb48fd000 0xb48fd000 13788
...
```
  In this situation we were deallocating the old chunk, and
  allocating a new one for every single one of those, but now we can
  keep the same chunk (we just updated the header), which saves some
  heap operations.

Reviewers: hctim, morehouse, vitalybuka, eugenis, cferris, rengolin

Reviewed By: morehouse

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

Tags: #llvm, #sanitizers

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

llvm-svn: 371628
2019-09-11 14:48:41 +00:00
Kostya Kortchinsky 3e5360f194 [scudo][standalone] Fix malloc_iterate
Summary:
cferris's Bionic tests found an issue in Scudo's `malloc_iterate`.

We were inclusive of both boundaries, which resulted in a `Block` that
was located on said boundary to be possibly accounted for twice, or
just being accounted for while iterating on regions that are not ours
(usually the unmapped ones in between Primary regions).

The fix is to exclude the upper boundary in `iterateOverChunks`, and
add a regression test.

This additionally corrects a typo in a comment, and change the 64-bit
Primary iteration function to not assume that `BatchClassId` is 0.

Reviewers: cferris, morehouse, hctim, vitalybuka, eugenis

Reviewed By: hctim

Subscribers: delcypher, #sanitizers, llvm-commits

Tags: #llvm, #sanitizers

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

llvm-svn: 369400
2019-08-20 16:17:08 +00:00
Kostya Kortchinsky 2be59170d4 [scudo][standalone] Add more stats to mallinfo
Summary:
Android requires additional stats in mallinfo. While we can provide
right away the number of bytes mapped (Primary+Secondary), there was
no way to get the number of free bytes (only makes sense for the
Primary since the Secondary unmaps everything on deallocation).

An approximation could be `StatMapped - StatAllocated`, but since we
are mapping in `1<<17` increments for the 64-bit Primary, it's fairly
inaccurate.

So we introduce `StatFree` (note it's `Free`, not `Freed`!), which
keeps track of the amount of Primary blocks currently unallocated.

Reviewers: cferris, eugenis, vitalybuka, hctim, morehouse

Reviewed By: morehouse

Subscribers: delcypher, #sanitizers, llvm-commits

Tags: #llvm, #sanitizers

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

llvm-svn: 368866
2019-08-14 16:04:01 +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
Kostya Kortchinsky 8f18a4c980 [scudo][standalone] NFC corrections
Summary:
A few corrections:
- rename `TransferBatch::MaxCached` to `getMaxCached` to conform with
  the style guide;
- move `getBlockBegin` from `Chunk::` to `Allocator::`: I believe it
  was a fallacy to have this be a `Chunk` method, as chunks'
  relationship to backend blocks are up to the frontend allocator. It
  makes more sense now, particularly with regard to the offset. Update
  the associated chunk test as the method isn't available there
  anymore;
- add a forgotten `\n` to a log string;
- for `releaseToOs`, instead of starting at `1`, start at `0` and
  `continue` on `BatchClassId`: in the end it's identical but doesn't
  assume a particular class id for batches;
- change a `CHECK` to a `reportOutOfMemory`: it's a clearer message

Reviewers: hctim, morehouse, eugenis, vitalybuka

Reviewed By: hctim

Subscribers: delcypher, #sanitizers, llvm-commits

Tags: #llvm, #sanitizers

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

llvm-svn: 365816
2019-07-11 19:55:53 +00:00
Kostya Kortchinsky aeb3826228 [scudo][standalone] Merge Spin & Blocking mutex into a Hybrid one
Summary:
We ran into a problem on Fuchsia where yielding threads would never
be deboosted, ultimately resulting in several threads spinning on the
same TSD, and no possibility for another thread to be scheduled,
dead-locking the process.

While this was fixed in Zircon, this lead to discussions about if
spinning without a break condition was a good decision, and settled on
a new hybrid model that would spin for a while then block.

Currently we are using a number of iterations for spinning that is
mostly arbitrary (based on sanitizer_common values), but this can
be tuned in the future.

Since we are touching `common.h`, we also use this change as a vehicle
for an Android optimization (the page size is fixed in Bionic, so use
a fixed value too).

Reviewers: morehouse, hctim, eugenis, dvyukov, vitalybuka

Reviewed By: hctim

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

Tags: #llvm, #sanitizers

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

llvm-svn: 365790
2019-07-11 15:32:26 +00:00
Kostya Kortchinsky f50a953ea7 [scudo][standalone] Link tests against libatomic
Summary:
Some clang versions (< 6.0) do not inline the atomic builtin functions
leaving unresolved references to `__atomic_load_8` and so on (seems to
be mostly 64-bit atomics on 32-bit platforms).
I tried without success to use some cmake magic to detect when that
would be the case, and decided to fall back to unconditionally
linking libatomic.

Reviewers: morehouse, eugenis, vitalybuka, hctim, tejohnson

Reviewed By: tejohnson

Subscribers: mgorny, delcypher, jfb, #sanitizers, llvm-commits

Tags: #llvm, #sanitizers

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

llvm-svn: 365052
2019-07-03 16:32:01 +00:00
Kostya Kortchinsky d63d14f76b [scudo][standalone] Potential fix for missing sized delete
Summary:
In some setups, using `-fsized-deallocation` would end up not finding
a sized delete operator at link time. For now, avoid using the flag
and declare the sized delete operator in the cpp test only.

This is a tentative fix as I do not have the failing setup.

Reviewers: rnk, morehouse, hctim, eugenis, vitalybuka

Reviewed By: rnk, hctim

Subscribers: mgorny, delcypher, #sanitizers, llvm-commits

Tags: #llvm, #sanitizers

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

llvm-svn: 365045
2019-07-03 14:38:47 +00:00
Reid Kleckner adeab8d754 Revert Remove scudo standalone tests from check-all
This reverts r364877 (git commit dfae3705b7)

This didn't solve my problem so I've reverted it.

llvm-svn: 364878
2019-07-01 23:53:16 +00:00
Reid Kleckner dfae3705b7 Remove scudo standalone tests from check-all
They appear to fail to link in various 32-bit configurations for unknown
reasons. This change was already reverted, and it seems preferable to me
to make forward progress and remove this once the problems are fully
understood.

llvm-svn: 364877
2019-07-01 23:29:59 +00:00
Kostya Kortchinsky d44cb7a656 [scudo][standalone] Introduce the C & C++ wrappers [fixed]
Summary:
This is a redo of D63612.

Two problems came up on some bots:
- `__builtin_umull_overflow` was not declared. This is likely due to an
  older clang or gcc, so add a guard with `__has_builtin` and fallback
  to a division in the event the builtin doesn't exist;
- contradicting definition for `malloc`, etc. This is AFAIU due to the
  fact that we ended up transitively including `stdlib.h` in the `.inc`
  due to it being the flags parser header: so move the include to the
  cc instead.

This should fix the issues, but since those didn't come up in my local
tests it's mostly guesswork.

Rest is the same!

Reviewers: morehouse, hctim, eugenis, vitalybuka, dyung, hans

Reviewed By: morehouse, dyung, hans

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

Tags: #llvm, #sanitizers

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

llvm-svn: 364547
2019-06-27 14:23:26 +00:00
Hans Wennborg 1a0810407e Revert r364332 "[scudo][standalone] Introduce the C & C++ wrappers"
Makes the build fail with e.g.

  llvm/projects/compiler-rt/lib/scudo/standalone/wrappers_c.inc:20:68: error:
  declaration of 'void* calloc(size_t, size_t)' has a different exception
  specifier
   INTERFACE WEAK void *SCUDO_PREFIX(calloc)(size_t nmemb, size_t size) {
                                                                      ^

See llvm-commits thread.

> Summary:
> This CL adds C & C++ wrappers and associated tests. Those use default
> configurations for a Scudo combined allocator that will likely be
> tweaked in the future.
>
> This is the final CL required to have a functional C & C++ allocator
> based on Scudo.
>
> The structure I have chosen is to define the core C allocation
> primitives in an `.inc` file that can be customized through defines.
> This allows to easily have 2 (or more) sets of wrappers backed by
> different combined allocators, as demonstrated by the `Bionic`
> wrappers: one set for the "default" allocator, one set for the "svelte"
> allocator.
>
> Currently all the tests added have been gtests, but I am planning to
> add some more lit tests as well.
>
> Reviewers: morehouse, eugenis, vitalybuka, hctim, rengolin
>
> Reviewed By: morehouse
>
> Subscribers: srhines, mgorny, delcypher, jfb, #sanitizers, llvm-commits
>
> Tags: #llvm, #sanitizers
>
> Differential Revision: https://reviews.llvm.org/D63612

llvm-svn: 364400
2019-06-26 09:46:26 +00:00
Kostya Kortchinsky 37340e3cd6 [scudo][standalone] Introduce the C & C++ wrappers
Summary:
This CL adds C & C++ wrappers and associated tests. Those use default
configurations for a Scudo combined allocator that will likely be
tweaked in the future.

This is the final CL required to have a functional C & C++ allocator
based on Scudo.

The structure I have chosen is to define the core C allocation
primitives in an `.inc` file that can be customized through defines.
This allows to easily have 2 (or more) sets of wrappers backed by
different combined allocators, as demonstrated by the `Bionic`
wrappers: one set for the "default" allocator, one set for the "svelte"
allocator.

Currently all the tests added have been gtests, but I am planning to
add some more lit tests as well.

Reviewers: morehouse, eugenis, vitalybuka, hctim, rengolin

Reviewed By: morehouse

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

Tags: #llvm, #sanitizers

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

llvm-svn: 364332
2019-06-25 16:51:27 +00:00
Kostya Kortchinsky e4eadf174c [scudo][standalone] Introduce the combined allocator
Summary:
The Combined allocator hold together all the other components, and
provides a memory allocator interface based on various template
parameters. This will be in turn used by "wrappers" that will provide
the standard C and C++ memory allocation functions, but can be
used as is as well.

This doesn't depart significantly from the current Scudo implementation
except for a few details:
- Quarantine batches are now protected by a header a well;
- an Allocator instance has its own TSD registry, as opposed to a
  static one for everybody;
- a function to iterate over busy chunks has been added, for Android
  purposes;

This also adds the associated tests, and a few default configurations
for several platforms, that will likely be further tuned later on.

Reviewers: morehouse, hctim, eugenis, vitalybuka

Reviewed By: morehouse

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

Tags: #llvm, #sanitizers

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

llvm-svn: 363569
2019-06-17 15:23:11 +00:00
Kostya Kortchinsky 624a24e156 [scudo][standalone] Unmap memory in tests
Summary:
The more tests are added, the more we are limited by the size of the
address space on 32-bit. Implement `unmapTestOnly` all around (like it
is in sanitzer_common) to be able to free up some memory.
This is not intended to be a proper "destructor" for an allocator, but
allows us to not fail due to having no memory left.

Reviewers: morehouse, vitalybuka, eugenis, hctim

Reviewed By: morehouse

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

Tags: #llvm, #sanitizers

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

llvm-svn: 363095
2019-06-11 19:50:12 +00:00
Kostya Kortchinsky 52bfd673d1 [scudo][standalone] Introduce the thread specific data structures
Summary:
This CL adds the structures dealing with thread specific data for the
allocator. This includes the thread specific data structure itself and
two registries for said structures: an exclusive one, where each thread
will have its own TSD struct, and a shared one, where a pool of TSD
structs will be shared by all threads, with dynamic reassignment at
runtime based on contention.

This departs from the current Scudo implementation: we intend to make
the Registry a template parameter of the allocator (as opposed to a
single global entity), allowing various allocators to coexist with
different TSD registry models. As a result, TSD registry and Allocator
are tightly coupled.

This also corrects a couple of things in other files that I noticed
while adding this.

Reviewers: eugenis, vitalybuka, morehouse, hctim

Reviewed By: morehouse

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

Tags: #llvm, #sanitizers

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

llvm-svn: 362962
2019-06-10 16:50:52 +00:00