[compiler-rt] r224395 - [ASan] Introduce SetCanPoisonMemory() function.

Alexey Samsonov vonosmas at gmail.com
Tue Dec 16 16:01:02 PST 2014


Author: samsonov
Date: Tue Dec 16 18:01:02 2014
New Revision: 224395

URL: http://llvm.org/viewvc/llvm-project?rev=224395&view=rev
Log:
[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.

Modified:
    compiler-rt/trunk/lib/asan/asan_activation.cc
    compiler-rt/trunk/lib/asan/asan_allocator2.cc
    compiler-rt/trunk/lib/asan/asan_globals.cc
    compiler-rt/trunk/lib/asan/asan_poisoning.cc
    compiler-rt/trunk/lib/asan/asan_poisoning.h
    compiler-rt/trunk/lib/asan/asan_rtl.cc

Modified: compiler-rt/trunk/lib/asan/asan_activation.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_activation.cc?rev=224395&r1=224394&r2=224395&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_activation.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_activation.cc Tue Dec 16 18:01:02 2014
@@ -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);
 }

Modified: compiler-rt/trunk/lib/asan/asan_allocator2.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_allocator2.cc?rev=224395&r1=224394&r2=224395&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_allocator2.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_allocator2.cc Tue Dec 16 18:01:02 2014
@@ -312,9 +312,9 @@ static void *Allocate(uptr size, uptr al
     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 al
   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;
   }

Modified: compiler-rt/trunk/lib/asan/asan_globals.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_globals.cc?rev=224395&r1=224394&r2=224395&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_globals.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_globals.cc Tue Dec 16 18:01:02 2014
@@ -164,7 +164,7 @@ static void RegisterGlobal(const Global
       }
     }
   }
-  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 Globa
   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_gl
 // 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 ch
 // 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);

Modified: compiler-rt/trunk/lib/asan/asan_poisoning.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_poisoning.cc?rev=224395&r1=224394&r2=224395&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_poisoning.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_poisoning.cc Tue Dec 16 18:01:02 2014
@@ -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(upt
                                      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);

Modified: compiler-rt/trunk/lib/asan/asan_poisoning.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_poisoning.h?rev=224395&r1=224394&r2=224395&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_poisoning.h (original)
+++ compiler-rt/trunk/lib/asan/asan_poisoning.h Tue Dec 16 18:01:02 2014
@@ -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(upt
 // 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
 
 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++) {

Modified: compiler-rt/trunk/lib/asan/asan_rtl.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_rtl.cc?rev=224395&r1=224394&r2=224395&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_rtl.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_rtl.cc Tue Dec 16 18:01:02 2014
@@ -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();





More information about the llvm-commits mailing list