[GWP-ASan] Core Guarded Pool Allocator [4].
Summary:
See D60593 for further information.
This patch introduces the core of GWP-ASan, being the guarded pool allocator. This class contains the logic for creating and maintaining allocations in the guarded pool. Its public interface is to be utilised by supporting allocators in order to provide sampled guarded allocation behaviour.
This patch also contains basic functionality tests of the allocator as unittests. The error-catching behaviour will be tested in upcoming patches that use Scudo as an implementing allocator.
Reviewers: vlad.tsyrklevich, eugenis, jfb
Reviewed By: vlad.tsyrklevich
Subscribers: dexonsmith, kubamracek, mgorny, cryptoad, jfb, #sanitizers, llvm-commits, morehouse
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D62872
llvm-svn: 362636
2019-06-06 03:42:48 +08:00
|
|
|
//===-- guarded_pool_allocator.h --------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef GWP_ASAN_GUARDED_POOL_ALLOCATOR_H_
|
|
|
|
#define GWP_ASAN_GUARDED_POOL_ALLOCATOR_H_
|
|
|
|
|
|
|
|
#include "gwp_asan/definitions.h"
|
|
|
|
#include "gwp_asan/mutex.h"
|
|
|
|
#include "gwp_asan/options.h"
|
|
|
|
#include "gwp_asan/random.h"
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
namespace gwp_asan {
|
|
|
|
// This class is the primary implementation of the allocator portion of GWP-
|
|
|
|
// ASan. It is the sole owner of the pool of sequentially allocated guarded
|
|
|
|
// slots. It should always be treated as a singleton.
|
|
|
|
|
|
|
|
// Functions in the public interface of this class are thread-compatible until
|
|
|
|
// init() is called, at which point they become thread-safe (unless specified
|
|
|
|
// otherwise).
|
|
|
|
class GuardedPoolAllocator {
|
|
|
|
public:
|
|
|
|
static constexpr uint64_t kInvalidThreadID = UINT64_MAX;
|
|
|
|
|
|
|
|
enum class Error {
|
|
|
|
UNKNOWN,
|
|
|
|
USE_AFTER_FREE,
|
|
|
|
DOUBLE_FREE,
|
|
|
|
INVALID_FREE,
|
|
|
|
BUFFER_OVERFLOW,
|
|
|
|
BUFFER_UNDERFLOW
|
|
|
|
};
|
|
|
|
|
|
|
|
struct AllocationMetadata {
|
|
|
|
// Maximum number of stack trace frames to collect for allocations + frees.
|
|
|
|
// TODO(hctim): Implement stack frame compression, a-la Chromium.
|
[GWP-ASan] Add generic unwinders and structure backtrace output.
Summary:
Adds two flavours of generic unwinder and all the supporting cruft. If the
supporting allocator is okay with bringing in sanitizer_common, they can use
the fast frame-pointer based unwinder from sanitizer_common. Otherwise, we also
provide the backtrace() libc-based unwinder as well. Of course, the allocator
can always specify its own unwinder and unwinder-symbolizer.
The slightly changed output format is exemplified in the first comment on this
patch. It now better incorporates backtrace information, and displays
allocation details on the second line.
Reviewers: eugenis, vlad.tsyrklevich
Reviewed By: eugenis, vlad.tsyrklevich
Subscribers: srhines, kubamracek, mgorny, cryptoad, #sanitizers, llvm-commits, morehouse
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D63841
llvm-svn: 364941
2019-07-03 00:04:52 +08:00
|
|
|
static constexpr size_t kMaximumStackFrames = 64;
|
[GWP-ASan] Core Guarded Pool Allocator [4].
Summary:
See D60593 for further information.
This patch introduces the core of GWP-ASan, being the guarded pool allocator. This class contains the logic for creating and maintaining allocations in the guarded pool. Its public interface is to be utilised by supporting allocators in order to provide sampled guarded allocation behaviour.
This patch also contains basic functionality tests of the allocator as unittests. The error-catching behaviour will be tested in upcoming patches that use Scudo as an implementing allocator.
Reviewers: vlad.tsyrklevich, eugenis, jfb
Reviewed By: vlad.tsyrklevich
Subscribers: dexonsmith, kubamracek, mgorny, cryptoad, jfb, #sanitizers, llvm-commits, morehouse
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D62872
llvm-svn: 362636
2019-06-06 03:42:48 +08:00
|
|
|
|
[GWP-ASan] Add generic unwinders and structure backtrace output.
Summary:
Adds two flavours of generic unwinder and all the supporting cruft. If the
supporting allocator is okay with bringing in sanitizer_common, they can use
the fast frame-pointer based unwinder from sanitizer_common. Otherwise, we also
provide the backtrace() libc-based unwinder as well. Of course, the allocator
can always specify its own unwinder and unwinder-symbolizer.
The slightly changed output format is exemplified in the first comment on this
patch. It now better incorporates backtrace information, and displays
allocation details on the second line.
Reviewers: eugenis, vlad.tsyrklevich
Reviewed By: eugenis, vlad.tsyrklevich
Subscribers: srhines, kubamracek, mgorny, cryptoad, #sanitizers, llvm-commits, morehouse
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D63841
llvm-svn: 364941
2019-07-03 00:04:52 +08:00
|
|
|
// Records the given allocation metadata into this struct.
|
|
|
|
void RecordAllocation(uintptr_t Addr, size_t Size,
|
|
|
|
options::Backtrace_t Backtrace);
|
[GWP-ASan] Core Guarded Pool Allocator [4].
Summary:
See D60593 for further information.
This patch introduces the core of GWP-ASan, being the guarded pool allocator. This class contains the logic for creating and maintaining allocations in the guarded pool. Its public interface is to be utilised by supporting allocators in order to provide sampled guarded allocation behaviour.
This patch also contains basic functionality tests of the allocator as unittests. The error-catching behaviour will be tested in upcoming patches that use Scudo as an implementing allocator.
Reviewers: vlad.tsyrklevich, eugenis, jfb
Reviewed By: vlad.tsyrklevich
Subscribers: dexonsmith, kubamracek, mgorny, cryptoad, jfb, #sanitizers, llvm-commits, morehouse
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D62872
llvm-svn: 362636
2019-06-06 03:42:48 +08:00
|
|
|
|
[GWP-ASan] Add generic unwinders and structure backtrace output.
Summary:
Adds two flavours of generic unwinder and all the supporting cruft. If the
supporting allocator is okay with bringing in sanitizer_common, they can use
the fast frame-pointer based unwinder from sanitizer_common. Otherwise, we also
provide the backtrace() libc-based unwinder as well. Of course, the allocator
can always specify its own unwinder and unwinder-symbolizer.
The slightly changed output format is exemplified in the first comment on this
patch. It now better incorporates backtrace information, and displays
allocation details on the second line.
Reviewers: eugenis, vlad.tsyrklevich
Reviewed By: eugenis, vlad.tsyrklevich
Subscribers: srhines, kubamracek, mgorny, cryptoad, #sanitizers, llvm-commits, morehouse
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D63841
llvm-svn: 364941
2019-07-03 00:04:52 +08:00
|
|
|
// Record that this allocation is now deallocated.
|
|
|
|
void RecordDeallocation(options::Backtrace_t Backtrace);
|
[GWP-ASan] Core Guarded Pool Allocator [4].
Summary:
See D60593 for further information.
This patch introduces the core of GWP-ASan, being the guarded pool allocator. This class contains the logic for creating and maintaining allocations in the guarded pool. Its public interface is to be utilised by supporting allocators in order to provide sampled guarded allocation behaviour.
This patch also contains basic functionality tests of the allocator as unittests. The error-catching behaviour will be tested in upcoming patches that use Scudo as an implementing allocator.
Reviewers: vlad.tsyrklevich, eugenis, jfb
Reviewed By: vlad.tsyrklevich
Subscribers: dexonsmith, kubamracek, mgorny, cryptoad, jfb, #sanitizers, llvm-commits, morehouse
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D62872
llvm-svn: 362636
2019-06-06 03:42:48 +08:00
|
|
|
|
|
|
|
struct CallSiteInfo {
|
|
|
|
// The backtrace to the allocation/deallocation. If the first value is
|
|
|
|
// zero, we did not collect a trace.
|
|
|
|
uintptr_t Trace[kMaximumStackFrames] = {};
|
|
|
|
// The thread ID for this trace, or kInvalidThreadID if not available.
|
|
|
|
uint64_t ThreadID = kInvalidThreadID;
|
|
|
|
};
|
|
|
|
|
|
|
|
// The address of this allocation.
|
|
|
|
uintptr_t Addr = 0;
|
|
|
|
// Represents the actual size of the allocation.
|
|
|
|
size_t Size = 0;
|
|
|
|
|
|
|
|
CallSiteInfo AllocationTrace;
|
|
|
|
CallSiteInfo DeallocationTrace;
|
|
|
|
|
|
|
|
// Whether this allocation has been deallocated yet.
|
|
|
|
bool IsDeallocated = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
// During program startup, we must ensure that memory allocations do not land
|
|
|
|
// in this allocation pool if the allocator decides to runtime-disable
|
|
|
|
// GWP-ASan. The constructor value-initialises the class such that if no
|
|
|
|
// further initialisation takes place, calls to shouldSample() and
|
|
|
|
// pointerIsMine() will return false.
|
|
|
|
constexpr GuardedPoolAllocator(){};
|
|
|
|
GuardedPoolAllocator(const GuardedPoolAllocator &) = delete;
|
|
|
|
GuardedPoolAllocator &operator=(const GuardedPoolAllocator &) = delete;
|
|
|
|
|
|
|
|
// Note: This class is expected to be a singleton for the lifetime of the
|
|
|
|
// program. If this object is initialised, it will leak the guarded page pool
|
|
|
|
// and metadata allocations during destruction. We can't clean up these areas
|
|
|
|
// as this may cause a use-after-free on shutdown.
|
|
|
|
~GuardedPoolAllocator() = default;
|
|
|
|
|
|
|
|
// Initialise the rest of the members of this class. Create the allocation
|
|
|
|
// pool using the provided options. See options.inc for runtime configuration
|
|
|
|
// options.
|
|
|
|
void init(const options::Options &Opts);
|
|
|
|
|
|
|
|
// Return whether the allocation should be randomly chosen for sampling.
|
|
|
|
ALWAYS_INLINE bool shouldSample() {
|
|
|
|
// NextSampleCounter == 0 means we "should regenerate the counter".
|
|
|
|
// == 1 means we "should sample this allocation".
|
[GWP-ASan] Guard against recursive allocs. Pack TLS for perf.
Summary:
Add a recursivity guard for GPA::allocate(). This means that any
recursive allocations will fall back to the supporting allocator. In future
patches, we will introduce stack trace collection support. The unwinder will be
provided by the supporting allocator, and we can't guarantee they don't call
malloc() (e.g. backtrace() on posix may call dlopen(), which may call malloc().
Furthermore, this patch packs the new TLS recursivity guard into a thread local
struct, so that TLS variables should be hopefully not fall across cache lines.
Reviewers: vlad.tsyrklevich, morehouse, eugenis
Reviewed By: eugenis
Subscribers: kubamracek, #sanitizers, llvm-commits, eugenis
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D63736
llvm-svn: 364356
2019-06-26 06:29:05 +08:00
|
|
|
if (UNLIKELY(ThreadLocals.NextSampleCounter == 0))
|
|
|
|
ThreadLocals.NextSampleCounter =
|
|
|
|
(getRandomUnsigned32() % AdjustedSampleRate) + 1;
|
|
|
|
|
|
|
|
return UNLIKELY(--ThreadLocals.NextSampleCounter == 0);
|
[GWP-ASan] Core Guarded Pool Allocator [4].
Summary:
See D60593 for further information.
This patch introduces the core of GWP-ASan, being the guarded pool allocator. This class contains the logic for creating and maintaining allocations in the guarded pool. Its public interface is to be utilised by supporting allocators in order to provide sampled guarded allocation behaviour.
This patch also contains basic functionality tests of the allocator as unittests. The error-catching behaviour will be tested in upcoming patches that use Scudo as an implementing allocator.
Reviewers: vlad.tsyrklevich, eugenis, jfb
Reviewed By: vlad.tsyrklevich
Subscribers: dexonsmith, kubamracek, mgorny, cryptoad, jfb, #sanitizers, llvm-commits, morehouse
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D62872
llvm-svn: 362636
2019-06-06 03:42:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Returns whether the provided pointer is a current sampled allocation that
|
|
|
|
// is owned by this pool.
|
|
|
|
ALWAYS_INLINE bool pointerIsMine(const void *Ptr) const {
|
|
|
|
uintptr_t P = reinterpret_cast<uintptr_t>(Ptr);
|
|
|
|
return GuardedPagePool <= P && P < GuardedPagePoolEnd;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Allocate memory in a guarded slot, and return a pointer to the new
|
|
|
|
// allocation. Returns nullptr if the pool is empty, the requested size is too
|
|
|
|
// large for this pool to handle, or the requested size is zero.
|
|
|
|
void *allocate(size_t Size);
|
|
|
|
|
|
|
|
// Deallocate memory in a guarded slot. The provided pointer must have been
|
|
|
|
// allocated using this pool. This will set the guarded slot as inaccessible.
|
|
|
|
void deallocate(void *Ptr);
|
|
|
|
|
|
|
|
// Returns the size of the allocation at Ptr.
|
|
|
|
size_t getSize(const void *Ptr);
|
|
|
|
|
|
|
|
// Returns the largest allocation that is supported by this pool. Any
|
|
|
|
// allocations larger than this should go to the regular system allocator.
|
|
|
|
size_t maximumAllocationSize() const;
|
|
|
|
|
|
|
|
// Dumps an error report (including allocation and deallocation stack traces).
|
|
|
|
// An optional error may be provided if the caller knows what the error is
|
|
|
|
// ahead of time. This is primarily a helper function to locate the static
|
|
|
|
// singleton pointer and call the internal version of this function. This
|
|
|
|
// method is never thread safe, and should only be called when fatal errors
|
|
|
|
// occur.
|
2019-06-06 16:04:33 +08:00
|
|
|
static void reportError(uintptr_t AccessPtr, Error E = Error::UNKNOWN);
|
[GWP-ASan] Core Guarded Pool Allocator [4].
Summary:
See D60593 for further information.
This patch introduces the core of GWP-ASan, being the guarded pool allocator. This class contains the logic for creating and maintaining allocations in the guarded pool. Its public interface is to be utilised by supporting allocators in order to provide sampled guarded allocation behaviour.
This patch also contains basic functionality tests of the allocator as unittests. The error-catching behaviour will be tested in upcoming patches that use Scudo as an implementing allocator.
Reviewers: vlad.tsyrklevich, eugenis, jfb
Reviewed By: vlad.tsyrklevich
Subscribers: dexonsmith, kubamracek, mgorny, cryptoad, jfb, #sanitizers, llvm-commits, morehouse
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D62872
llvm-svn: 362636
2019-06-06 03:42:48 +08:00
|
|
|
|
|
|
|
private:
|
|
|
|
static constexpr size_t kInvalidSlotID = SIZE_MAX;
|
|
|
|
|
|
|
|
// These functions anonymously map memory or change the permissions of mapped
|
|
|
|
// memory into this process in a platform-specific way. Pointer and size
|
|
|
|
// arguments are expected to be page-aligned. These functions will never
|
|
|
|
// return on error, instead electing to kill the calling process on failure.
|
|
|
|
// Note that memory is initially mapped inaccessible. In order for RW
|
|
|
|
// mappings, call mapMemory() followed by markReadWrite() on the returned
|
|
|
|
// pointer.
|
|
|
|
void *mapMemory(size_t Size) const;
|
|
|
|
void markReadWrite(void *Ptr, size_t Size) const;
|
|
|
|
void markInaccessible(void *Ptr, size_t Size) const;
|
|
|
|
|
|
|
|
// Get the current thread ID, or kInvalidThreadID if failure. Note: This
|
|
|
|
// implementation is platform-specific.
|
|
|
|
static uint64_t getThreadID();
|
|
|
|
|
|
|
|
// Get the page size from the platform-specific implementation. Only needs to
|
|
|
|
// be called once, and the result should be cached in PageSize in this class.
|
|
|
|
static size_t getPlatformPageSize();
|
|
|
|
|
|
|
|
// Install the SIGSEGV crash handler for printing use-after-free and heap-
|
|
|
|
// buffer-{under|over}flow exceptions. This is platform specific as even
|
|
|
|
// though POSIX and Windows both support registering handlers through
|
|
|
|
// signal(), we have to use platform-specific signal handlers to obtain the
|
|
|
|
// address that caused the SIGSEGV exception.
|
|
|
|
static void installSignalHandlers();
|
|
|
|
|
|
|
|
// Returns the index of the slot that this pointer resides in. If the pointer
|
|
|
|
// is not owned by this pool, the result is undefined.
|
|
|
|
size_t addrToSlot(uintptr_t Ptr) const;
|
|
|
|
|
|
|
|
// Returns the address of the N-th guarded slot.
|
|
|
|
uintptr_t slotToAddr(size_t N) const;
|
|
|
|
|
|
|
|
// Returns a pointer to the metadata for the owned pointer. If the pointer is
|
|
|
|
// not owned by this pool, the result is undefined.
|
|
|
|
AllocationMetadata *addrToMetadata(uintptr_t Ptr) const;
|
|
|
|
|
|
|
|
// Returns the address of the page that this pointer resides in.
|
|
|
|
uintptr_t getPageAddr(uintptr_t Ptr) const;
|
|
|
|
|
|
|
|
// Gets the nearest slot to the provided address.
|
|
|
|
size_t getNearestSlot(uintptr_t Ptr) const;
|
|
|
|
|
|
|
|
// Returns whether the provided pointer is a guard page or not. The pointer
|
|
|
|
// must be within memory owned by this pool, else the result is undefined.
|
|
|
|
bool isGuardPage(uintptr_t Ptr) const;
|
|
|
|
|
|
|
|
// Reserve a slot for a new guarded allocation. Returns kInvalidSlotID if no
|
|
|
|
// slot is available to be reserved.
|
|
|
|
size_t reserveSlot();
|
|
|
|
|
|
|
|
// Unreserve the guarded slot.
|
|
|
|
void freeSlot(size_t SlotIndex);
|
|
|
|
|
|
|
|
// Returns the offset (in bytes) between the start of a guarded slot and where
|
|
|
|
// the start of the allocation should take place. Determined using the size of
|
|
|
|
// the allocation and the options provided at init-time.
|
|
|
|
uintptr_t allocationSlotOffset(size_t AllocationSize) const;
|
|
|
|
|
|
|
|
// Returns the diagnosis for an unknown error. If the diagnosis is not
|
|
|
|
// Error::INVALID_FREE or Error::UNKNOWN, the metadata for the slot
|
|
|
|
// responsible for the error is placed in *Meta.
|
|
|
|
Error diagnoseUnknownError(uintptr_t AccessPtr, AllocationMetadata **Meta);
|
|
|
|
|
2019-06-06 16:04:33 +08:00
|
|
|
void reportErrorInternal(uintptr_t AccessPtr, Error E);
|
[GWP-ASan] Core Guarded Pool Allocator [4].
Summary:
See D60593 for further information.
This patch introduces the core of GWP-ASan, being the guarded pool allocator. This class contains the logic for creating and maintaining allocations in the guarded pool. Its public interface is to be utilised by supporting allocators in order to provide sampled guarded allocation behaviour.
This patch also contains basic functionality tests of the allocator as unittests. The error-catching behaviour will be tested in upcoming patches that use Scudo as an implementing allocator.
Reviewers: vlad.tsyrklevich, eugenis, jfb
Reviewed By: vlad.tsyrklevich
Subscribers: dexonsmith, kubamracek, mgorny, cryptoad, jfb, #sanitizers, llvm-commits, morehouse
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D62872
llvm-svn: 362636
2019-06-06 03:42:48 +08:00
|
|
|
|
|
|
|
// Cached page size for this system in bytes.
|
|
|
|
size_t PageSize = 0;
|
|
|
|
|
|
|
|
// A mutex to protect the guarded slot and metadata pool for this class.
|
|
|
|
Mutex PoolMutex;
|
|
|
|
// The number of guarded slots that this pool holds.
|
|
|
|
size_t MaxSimultaneousAllocations = 0;
|
|
|
|
// Record the number allocations that we've sampled. We store this amount so
|
|
|
|
// that we don't randomly choose to recycle a slot that previously had an
|
|
|
|
// allocation before all the slots have been utilised.
|
|
|
|
size_t NumSampledAllocations = 0;
|
|
|
|
// Pointer to the pool of guarded slots. Note that this points to the start of
|
|
|
|
// the pool (which is a guard page), not a pointer to the first guarded page.
|
|
|
|
uintptr_t GuardedPagePool = UINTPTR_MAX;
|
|
|
|
uintptr_t GuardedPagePoolEnd = 0;
|
|
|
|
// Pointer to the allocation metadata (allocation/deallocation stack traces),
|
|
|
|
// if any.
|
|
|
|
AllocationMetadata *Metadata = nullptr;
|
|
|
|
|
|
|
|
// Pointer to an array of free slot indexes.
|
|
|
|
size_t *FreeSlots = nullptr;
|
|
|
|
// The current length of the list of free slots.
|
|
|
|
size_t FreeSlotsLength = 0;
|
|
|
|
|
|
|
|
// See options.{h, inc} for more information.
|
|
|
|
bool PerfectlyRightAlign = false;
|
|
|
|
|
|
|
|
// Printf function supplied by the implementing allocator. We can't (in
|
|
|
|
// general) use printf() from the cstdlib as it may malloc(), causing infinite
|
|
|
|
// recursion.
|
|
|
|
options::Printf_t Printf = nullptr;
|
[GWP-ASan] Add generic unwinders and structure backtrace output.
Summary:
Adds two flavours of generic unwinder and all the supporting cruft. If the
supporting allocator is okay with bringing in sanitizer_common, they can use
the fast frame-pointer based unwinder from sanitizer_common. Otherwise, we also
provide the backtrace() libc-based unwinder as well. Of course, the allocator
can always specify its own unwinder and unwinder-symbolizer.
The slightly changed output format is exemplified in the first comment on this
patch. It now better incorporates backtrace information, and displays
allocation details on the second line.
Reviewers: eugenis, vlad.tsyrklevich
Reviewed By: eugenis, vlad.tsyrklevich
Subscribers: srhines, kubamracek, mgorny, cryptoad, #sanitizers, llvm-commits, morehouse
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D63841
llvm-svn: 364941
2019-07-03 00:04:52 +08:00
|
|
|
options::Backtrace_t Backtrace = nullptr;
|
|
|
|
options::PrintBacktrace_t PrintBacktrace = nullptr;
|
[GWP-ASan] Core Guarded Pool Allocator [4].
Summary:
See D60593 for further information.
This patch introduces the core of GWP-ASan, being the guarded pool allocator. This class contains the logic for creating and maintaining allocations in the guarded pool. Its public interface is to be utilised by supporting allocators in order to provide sampled guarded allocation behaviour.
This patch also contains basic functionality tests of the allocator as unittests. The error-catching behaviour will be tested in upcoming patches that use Scudo as an implementing allocator.
Reviewers: vlad.tsyrklevich, eugenis, jfb
Reviewed By: vlad.tsyrklevich
Subscribers: dexonsmith, kubamracek, mgorny, cryptoad, jfb, #sanitizers, llvm-commits, morehouse
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D62872
llvm-svn: 362636
2019-06-06 03:42:48 +08:00
|
|
|
|
|
|
|
// The adjusted sample rate for allocation sampling. Default *must* be
|
|
|
|
// nonzero, as dynamic initialisation may call malloc (e.g. from libstdc++)
|
|
|
|
// before GPA::init() is called. This would cause an error in shouldSample(),
|
|
|
|
// where we would calculate modulo zero. This value is set UINT32_MAX, as when
|
|
|
|
// GWP-ASan is disabled, we wish to never spend wasted cycles recalculating
|
|
|
|
// the sample rate.
|
|
|
|
uint32_t AdjustedSampleRate = UINT32_MAX;
|
[GWP-ASan] Guard against recursive allocs. Pack TLS for perf.
Summary:
Add a recursivity guard for GPA::allocate(). This means that any
recursive allocations will fall back to the supporting allocator. In future
patches, we will introduce stack trace collection support. The unwinder will be
provided by the supporting allocator, and we can't guarantee they don't call
malloc() (e.g. backtrace() on posix may call dlopen(), which may call malloc().
Furthermore, this patch packs the new TLS recursivity guard into a thread local
struct, so that TLS variables should be hopefully not fall across cache lines.
Reviewers: vlad.tsyrklevich, morehouse, eugenis
Reviewed By: eugenis
Subscribers: kubamracek, #sanitizers, llvm-commits, eugenis
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D63736
llvm-svn: 364356
2019-06-26 06:29:05 +08:00
|
|
|
|
|
|
|
// Pack the thread local variables into a struct to ensure that they're in
|
|
|
|
// the same cache line for performance reasons. These are the most touched
|
|
|
|
// variables in GWP-ASan.
|
|
|
|
struct alignas(8) ThreadLocalPackedVariables {
|
|
|
|
constexpr ThreadLocalPackedVariables() {}
|
|
|
|
// Thread-local decrementing counter that indicates that a given allocation
|
|
|
|
// should be sampled when it reaches zero.
|
|
|
|
uint32_t NextSampleCounter = 0;
|
|
|
|
// Guard against recursivity. Unwinders often contain complex behaviour that
|
|
|
|
// may not be safe for the allocator (i.e. the unwinder calls dlopen(),
|
|
|
|
// which calls malloc()). When recursive behaviour is detected, we will
|
|
|
|
// automatically fall back to the supporting allocator to supply the
|
|
|
|
// allocation.
|
|
|
|
bool RecursiveGuard = false;
|
|
|
|
};
|
|
|
|
static TLS_INITIAL_EXEC ThreadLocalPackedVariables ThreadLocals;
|
[GWP-ASan] Core Guarded Pool Allocator [4].
Summary:
See D60593 for further information.
This patch introduces the core of GWP-ASan, being the guarded pool allocator. This class contains the logic for creating and maintaining allocations in the guarded pool. Its public interface is to be utilised by supporting allocators in order to provide sampled guarded allocation behaviour.
This patch also contains basic functionality tests of the allocator as unittests. The error-catching behaviour will be tested in upcoming patches that use Scudo as an implementing allocator.
Reviewers: vlad.tsyrklevich, eugenis, jfb
Reviewed By: vlad.tsyrklevich
Subscribers: dexonsmith, kubamracek, mgorny, cryptoad, jfb, #sanitizers, llvm-commits, morehouse
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D62872
llvm-svn: 362636
2019-06-06 03:42:48 +08:00
|
|
|
};
|
|
|
|
} // namespace gwp_asan
|
|
|
|
|
|
|
|
#endif // GWP_ASAN_GUARDED_POOL_ALLOCATOR_H_
|