diff options
| author | Alexey Samsonov <vonosmas@gmail.com> | 2014-12-17 00:01:02 +0000 |
|---|---|---|
| committer | Alexey Samsonov <vonosmas@gmail.com> | 2014-12-17 00:01:02 +0000 |
| commit | 91bb25f515268aa52c8f2d08fdcd2f08d617585b (patch) | |
| tree | 80091fe77acf8dbbb5930175cecd67ec9dc5777c /compiler-rt | |
| parent | 0317bc9e55c9e4546416e8d141d4bca813adb67f (diff) | |
| download | bcm5719-llvm-91bb25f515268aa52c8f2d08fdcd2f08d617585b.tar.gz bcm5719-llvm-91bb25f515268aa52c8f2d08fdcd2f08d617585b.zip | |
[ASan] Introduce SetCanPoisonMemory() function.
SetCanPoisonMemory()/CanPoisonMemory() functions are now used
instead of "poison_heap" flag to determine if ASan is allowed
to poison the shadow memory. This allows to hot-patch this
value in runtime (e.g. during ASan activation) without introducing
a data race.
llvm-svn: 224395
Diffstat (limited to 'compiler-rt')
| -rw-r--r-- | compiler-rt/lib/asan/asan_activation.cc | 6 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_allocator2.cc | 6 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_globals.cc | 8 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_poisoning.cc | 15 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_poisoning.h | 8 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_rtl.cc | 1 |
6 files changed, 31 insertions, 13 deletions
diff --git a/compiler-rt/lib/asan/asan_activation.cc b/compiler-rt/lib/asan/asan_activation.cc index 02e09119271..8776f53fa4e 100644 --- a/compiler-rt/lib/asan/asan_activation.cc +++ b/compiler-rt/lib/asan/asan_activation.cc @@ -16,6 +16,7 @@ #include "asan_allocator.h" #include "asan_flags.h" #include "asan_internal.h" +#include "asan_poisoning.h" #include "asan_stack.h" #include "sanitizer_common/sanitizer_flags.h" @@ -62,12 +63,12 @@ void AsanActivate() { // Restore flag values. // FIXME: this is not atomic, and there may be other threads alive. flags()->max_redzone = asan_deactivated_flags.max_redzone; - flags()->poison_heap = asan_deactivated_flags.poison_heap; flags()->alloc_dealloc_mismatch = asan_deactivated_flags.alloc_dealloc_mismatch; ParseExtraActivationFlags(); + 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); @@ -77,7 +78,8 @@ void AsanActivate() { "malloc_context_size %d, alloc_dealloc_mismatch %d, " "allocator_may_return_null %d\n", asan_deactivated_flags.quarantine_size, flags()->max_redzone, - flags()->poison_heap, asan_deactivated_flags.malloc_context_size, + asan_deactivated_flags.poison_heap, + asan_deactivated_flags.malloc_context_size, flags()->alloc_dealloc_mismatch, asan_deactivated_flags.allocator_may_return_null); } diff --git a/compiler-rt/lib/asan/asan_allocator2.cc b/compiler-rt/lib/asan/asan_allocator2.cc index 8900c9746bc..a3ef524e100 100644 --- a/compiler-rt/lib/asan/asan_allocator2.cc +++ b/compiler-rt/lib/asan/asan_allocator2.cc @@ -312,9 +312,9 @@ static void *Allocate(uptr size, uptr alignment, BufferedStackTrace *stack, allocated = allocator.Allocate(cache, needed_size, 8, false); } - if (*(u8 *)MEM_TO_SHADOW((uptr)allocated) == 0 && flags()->poison_heap) { + if (*(u8 *)MEM_TO_SHADOW((uptr)allocated) == 0 && CanPoisonMemory()) { // Heap poisoning is enabled, but the allocator provides an unpoisoned - // chunk. This is possible if flags()->poison_heap was disabled for some + // chunk. This is possible if CanPoisonMemory() was false for some // time, for example, due to flags()->start_disabled. // Anyway, poison the block before using it for anything else. uptr allocated_size = allocator.GetActuallyAllocatedSize(allocated); @@ -362,7 +362,7 @@ static void *Allocate(uptr size, uptr alignment, BufferedStackTrace *stack, if (size_rounded_down_to_granularity) PoisonShadow(user_beg, size_rounded_down_to_granularity, 0); // Deal with the end of the region if size is not aligned to granularity. - if (size != size_rounded_down_to_granularity && fl.poison_heap) { + if (size != size_rounded_down_to_granularity && CanPoisonMemory()) { u8 *shadow = (u8*)MemToShadow(user_beg + size_rounded_down_to_granularity); *shadow = fl.poison_partial ? (size & (SHADOW_GRANULARITY - 1)) : 0; } diff --git a/compiler-rt/lib/asan/asan_globals.cc b/compiler-rt/lib/asan/asan_globals.cc index be111d4fb4c..c4571953c40 100644 --- a/compiler-rt/lib/asan/asan_globals.cc +++ b/compiler-rt/lib/asan/asan_globals.cc @@ -164,7 +164,7 @@ static void RegisterGlobal(const Global *g) { } } } - if (flags()->poison_heap) + if (CanPoisonMemory()) PoisonRedZones(*g); ListOfGlobals *l = new(allocator_for_globals) ListOfGlobals; l->g = g; @@ -186,7 +186,7 @@ static void UnregisterGlobal(const Global *g) { CHECK(AddrIsInMem(g->beg)); CHECK(AddrIsAlignedByGranularity(g->beg)); CHECK(AddrIsAlignedByGranularity(g->size_with_redzone)); - if (flags()->poison_heap) + if (CanPoisonMemory()) PoisonShadowForGlobal(g, 0); // We unpoison the shadow memory for the global but we do not remove it from // the list because that would require O(n^2) time with the current list @@ -249,7 +249,7 @@ void __asan_unregister_globals(__asan_global *globals, uptr n) { // initializer can only touch global variables in the same TU. void __asan_before_dynamic_init(const char *module_name) { if (!flags()->check_initialization_order || - !flags()->poison_heap) + !CanPoisonMemory()) return; bool strict_init_order = flags()->strict_init_order; CHECK(dynamic_init_globals); @@ -275,7 +275,7 @@ void __asan_before_dynamic_init(const char *module_name) { // TU are poisoned. It simply unpoisons all dynamically initialized globals. void __asan_after_dynamic_init() { if (!flags()->check_initialization_order || - !flags()->poison_heap) + !CanPoisonMemory()) return; CHECK(asan_inited); BlockingMutexLock lock(&mu_for_globals); diff --git a/compiler-rt/lib/asan/asan_poisoning.cc b/compiler-rt/lib/asan/asan_poisoning.cc index 1c6e92f69c6..11fa271b238 100644 --- a/compiler-rt/lib/asan/asan_poisoning.cc +++ b/compiler-rt/lib/asan/asan_poisoning.cc @@ -15,13 +15,24 @@ #include "asan_poisoning.h" #include "asan_report.h" #include "asan_stack.h" +#include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_flags.h" namespace __asan { +static atomic_uint8_t can_poison_memory; + +void SetCanPoisonMemory(bool value) { + atomic_store(&can_poison_memory, value, memory_order_release); +} + +bool CanPoisonMemory() { + return atomic_load(&can_poison_memory, memory_order_acquire); +} + void PoisonShadow(uptr addr, uptr size, u8 value) { - if (!flags()->poison_heap) return; + if (!CanPoisonMemory()) return; CHECK(AddrIsAlignedByGranularity(addr)); CHECK(AddrIsInMem(addr)); CHECK(AddrIsAlignedByGranularity(addr + size)); @@ -34,7 +45,7 @@ void PoisonShadowPartialRightRedzone(uptr addr, uptr size, uptr redzone_size, u8 value) { - if (!flags()->poison_heap) return; + if (!CanPoisonMemory()) return; CHECK(AddrIsAlignedByGranularity(addr)); CHECK(AddrIsInMem(addr)); FastPoisonShadowPartialRightRedzone(addr, size, redzone_size, value); diff --git a/compiler-rt/lib/asan/asan_poisoning.h b/compiler-rt/lib/asan/asan_poisoning.h index feda1a98454..73ae12fbc46 100644 --- a/compiler-rt/lib/asan/asan_poisoning.h +++ b/compiler-rt/lib/asan/asan_poisoning.h @@ -19,6 +19,10 @@ namespace __asan { +// Enable/disable memory poisoning. +void SetCanPoisonMemory(bool value); +bool CanPoisonMemory(); + // Poisons the shadow memory for "size" bytes starting from "addr". void PoisonShadow(uptr addr, uptr size, u8 value); @@ -34,7 +38,7 @@ void PoisonShadowPartialRightRedzone(uptr addr, // performance-critical code with care. ALWAYS_INLINE void FastPoisonShadow(uptr aligned_beg, uptr aligned_size, u8 value) { - DCHECK(flags()->poison_heap); + DCHECK(CanPoisonMemory()); uptr shadow_beg = MEM_TO_SHADOW(aligned_beg); uptr shadow_end = MEM_TO_SHADOW( aligned_beg + aligned_size - SHADOW_GRANULARITY) + 1; @@ -68,7 +72,7 @@ ALWAYS_INLINE void FastPoisonShadow(uptr aligned_beg, uptr aligned_size, ALWAYS_INLINE void FastPoisonShadowPartialRightRedzone( uptr aligned_addr, uptr size, uptr redzone_size, u8 value) { - DCHECK(flags()->poison_heap); + DCHECK(CanPoisonMemory()); bool poison_partial = flags()->poison_partial; u8 *shadow = (u8*)MEM_TO_SHADOW(aligned_addr); for (uptr i = 0; i < redzone_size; i += SHADOW_GRANULARITY, shadow++) { diff --git a/compiler-rt/lib/asan/asan_rtl.cc b/compiler-rt/lib/asan/asan_rtl.cc index 6cd018b3a71..e6d18355ed3 100644 --- a/compiler-rt/lib/asan/asan_rtl.cc +++ b/compiler-rt/lib/asan/asan_rtl.cc @@ -570,6 +570,7 @@ static void AsanInitInternal() { const char *options = GetEnv("ASAN_OPTIONS"); InitializeFlags(flags(), options); + SetCanPoisonMemory(flags()->poison_heap); SetMallocContextSize(common_flags()->malloc_context_size); InitializeHighMemEnd(); |

