Index: lib/asan/asan_activation.cc =================================================================== --- lib/asan/asan_activation.cc +++ lib/asan/asan_activation.cc @@ -23,12 +23,9 @@ namespace __asan { static struct AsanDeactivatedFlags { - int quarantine_size; - int max_redzone; + AllocatorOptions allocator_options; int malloc_context_size; bool poison_heap; - bool alloc_dealloc_mismatch; - bool allocator_may_return_null; } asan_deactivated_flags; static bool asan_is_deactivated; @@ -36,15 +33,10 @@ void AsanStartDeactivated() { VReport(1, "Deactivating ASan\n"); // Save flag values. - asan_deactivated_flags.quarantine_size = flags()->quarantine_size; - asan_deactivated_flags.max_redzone = flags()->max_redzone; - asan_deactivated_flags.poison_heap = flags()->poison_heap; + asan_deactivated_flags.allocator_options.SetFrom(flags(), common_flags()); asan_deactivated_flags.malloc_context_size = common_flags()->malloc_context_size; - asan_deactivated_flags.alloc_dealloc_mismatch = - flags()->alloc_dealloc_mismatch; - asan_deactivated_flags.allocator_may_return_null = - common_flags()->allocator_may_return_null; + asan_deactivated_flags.poison_heap = flags()->poison_heap; flags()->quarantine_size = 0; flags()->max_redzone = 16; @@ -60,12 +52,6 @@ if (!asan_is_deactivated) return; VReport(1, "Activating ASan\n"); - // Restore flag values. - // FIXME: this is not atomic, and there may be other threads alive. - flags()->max_redzone = asan_deactivated_flags.max_redzone; - flags()->alloc_dealloc_mismatch = - asan_deactivated_flags.alloc_dealloc_mismatch; - // FIXME: Avoid modifying global common_flags() and flags() and restrict the // set of supported flags that can be provided in activation. char buf[100]; @@ -77,18 +63,18 @@ SetCanPoisonMemory(asan_deactivated_flags.poison_heap); SetMallocContextSize(asan_deactivated_flags.malloc_context_size); - ReInitializeAllocator(asan_deactivated_flags.allocator_may_return_null, - asan_deactivated_flags.quarantine_size); + ReInitializeAllocator(asan_deactivated_flags.allocator_options); asan_is_deactivated = false; - VReport(1, "quarantine_size %d, max_redzone %d, poison_heap %d, " + VReport(1, "quarantine_size_mb %d, max_redzone %d, poison_heap %d, " "malloc_context_size %d, alloc_dealloc_mismatch %d, " "allocator_may_return_null %d\n", - asan_deactivated_flags.quarantine_size, flags()->max_redzone, + asan_deactivated_flags.allocator_options.quarantine_size_mb, + asan_deactivated_flags.allocator_options.max_redzone, asan_deactivated_flags.poison_heap, asan_deactivated_flags.malloc_context_size, - flags()->alloc_dealloc_mismatch, - asan_deactivated_flags.allocator_may_return_null); + asan_deactivated_flags.allocator_options.alloc_dealloc_mismatch, + asan_deactivated_flags.allocator_options.may_return_null); } } // namespace __asan Index: lib/asan/asan_allocator.h =================================================================== --- lib/asan/asan_allocator.h +++ lib/asan/asan_allocator.h @@ -15,6 +15,7 @@ #ifndef ASAN_ALLOCATOR_H #define ASAN_ALLOCATOR_H +#include "asan_flags.h" #include "asan_internal.h" #include "asan_interceptors.h" #include "sanitizer_common/sanitizer_allocator.h" @@ -31,8 +32,18 @@ static const uptr kNumberOfSizeClasses = 255; struct AsanChunk; -void InitializeAllocator(bool may_return_null, uptr quarantine_size); -void ReInitializeAllocator(bool may_return_null, uptr quarantine_size); +struct AllocatorOptions { + u32 quarantine_size_mb; + u16 min_redzone; + u16 max_redzone; + u8 may_return_null; + u8 alloc_dealloc_mismatch; + + void SetFrom(const Flags *f, const CommonFlags *cf); +}; + +void InitializeAllocator(const AllocatorOptions &options); +void ReInitializeAllocator(const AllocatorOptions &options); class AsanChunkView { public: Index: lib/asan/asan_allocator.cc =================================================================== --- lib/asan/asan_allocator.cc +++ lib/asan/asan_allocator.cc @@ -205,6 +205,14 @@ return reinterpret_cast(ms->quarantine_cache); } +void AllocatorOptions::SetFrom(const Flags *f, const CommonFlags *cf) { + quarantine_size_mb = f->quarantine_size >> 20; + min_redzone = f->redzone; + max_redzone = f->max_redzone; + may_return_null = cf->allocator_may_return_null; + alloc_dealloc_mismatch = f->alloc_dealloc_mismatch; +} + struct Allocator { static const uptr kMaxAllowedMallocSize = FIRST_32_SECOND_64(3UL << 30, 64UL << 30); @@ -217,19 +225,42 @@ AllocatorCache fallback_allocator_cache; QuarantineCache fallback_quarantine_cache; + // ------------------- Options -------------------------- + atomic_uint16_t min_redzone; + atomic_uint16_t max_redzone; + atomic_uint8_t alloc_dealloc_mismatch; + + // ------------------- Initialization ------------------------ explicit Allocator(LinkerInitialized) : quarantine(LINKER_INITIALIZED), fallback_quarantine_cache(LINKER_INITIALIZED) {} - // ------------------- Initialization ------------------------ - void Initialize(bool may_return_null, uptr quarantine_size) { - allocator.Init(may_return_null); - quarantine.Init(quarantine_size, kMaxThreadLocalQuarantine); + void CheckOptions(const AllocatorOptions &options) const { + CHECK_GE(options.min_redzone, 16); + CHECK_GE(options.max_redzone, options.min_redzone); + CHECK_LE(options.max_redzone, 2048); + CHECK(IsPowerOfTwo(options.min_redzone)); + CHECK(IsPowerOfTwo(options.max_redzone)); } - void ReInitialize(bool may_return_null, uptr quarantine_size) { - allocator.SetMayReturnNull(may_return_null); - quarantine.Init(quarantine_size, kMaxThreadLocalQuarantine); + void SharedInitCode(const AllocatorOptions &options) { + CheckOptions(options); + quarantine.Init((uptr)options.quarantine_size_mb << 20, + kMaxThreadLocalQuarantine); + atomic_store(&alloc_dealloc_mismatch, options.alloc_dealloc_mismatch, + memory_order_release); + atomic_store(&min_redzone, options.min_redzone, memory_order_release); + atomic_store(&max_redzone, options.max_redzone, memory_order_release); + } + + void Initialize(const AllocatorOptions &options) { + allocator.Init(options.may_return_null); + SharedInitCode(options); + } + + void ReInitialize(const AllocatorOptions &options) { + allocator.SetMayReturnNull(options.may_return_null); + SharedInitCode(options); } // -------------------- Helper methods. ------------------------- @@ -242,8 +273,9 @@ user_requested_size <= (1 << 14) - 256 ? 4 : user_requested_size <= (1 << 15) - 512 ? 5 : user_requested_size <= (1 << 16) - 1024 ? 6 : 7; - return Min(Max(rz_log, RZSize2Log(flags()->redzone)), - RZSize2Log(flags()->max_redzone)); + u32 min_rz = atomic_load(&min_redzone, memory_order_acquire); + u32 max_rz = atomic_load(&max_redzone, memory_order_acquire); + return Min(Max(rz_log, RZSize2Log(min_rz)), RZSize2Log(max_rz)); } // We have an address between two chunks, and we want to report just one. @@ -419,9 +451,12 @@ AllocType alloc_type) { CHECK_EQ(m->chunk_state, CHUNK_QUARANTINE); - if (m->alloc_type != alloc_type && flags()->alloc_dealloc_mismatch) - ReportAllocTypeMismatch((uptr)ptr, stack, - (AllocType)m->alloc_type, (AllocType)alloc_type); + if (m->alloc_type != alloc_type) { + if (atomic_load(&alloc_dealloc_mismatch, memory_order_acquire)) { + ReportAllocTypeMismatch((uptr)ptr, stack, (AllocType)m->alloc_type, + (AllocType)alloc_type); + } + } CHECK_GE(m->alloc_tid, 0); if (SANITIZER_WORDSIZE == 64) // On 32-bits this resides in user area. @@ -619,12 +654,12 @@ return GetStackTraceFromId(chunk_->free_context_id); } -void InitializeAllocator(bool may_return_null, uptr quarantine_size) { - instance.Initialize(may_return_null, quarantine_size); +void InitializeAllocator(const AllocatorOptions &options) { + instance.Initialize(options); } -void ReInitializeAllocator(bool may_return_null, uptr quarantine_size) { - instance.ReInitialize(may_return_null, quarantine_size); +void ReInitializeAllocator(const AllocatorOptions &options) { + instance.ReInitialize(options); } AsanChunkView FindHeapChunkByAddress(uptr addr) { Index: lib/asan/asan_flags.cc =================================================================== --- lib/asan/asan_flags.cc +++ lib/asan/asan_flags.cc @@ -50,11 +50,6 @@ "Requirement: redzone >= 16, is a power of two."); ParseFlag(str, &f->max_redzone, "max_redzone", "Maximal size (in bytes) of redzones around heap objects."); - CHECK_GE(f->redzone, 16); - CHECK_GE(f->max_redzone, f->redzone); - CHECK_LE(f->max_redzone, 2048); - CHECK(IsPowerOfTwo(f->redzone)); - CHECK(IsPowerOfTwo(f->max_redzone)); ParseFlag(str, &f->debug, "debug", "If set, prints some debugging information and does additional checks."); Index: lib/asan/asan_rtl.cc =================================================================== --- lib/asan/asan_rtl.cc +++ lib/asan/asan_rtl.cc @@ -391,8 +391,9 @@ AsanTSDInit(PlatformTSDDtor); InstallDeadlySignalHandlers(AsanOnSIGSEGV); - InitializeAllocator(common_flags()->allocator_may_return_null, - flags()->quarantine_size); + AllocatorOptions allocator_options; + allocator_options.SetFrom(flags(), common_flags()); + InitializeAllocator(allocator_options); MaybeStartBackgroudThread();