Home | History | Annotate | Line # | Download | only in asan
      1 //===-- asan_activation.cc --------------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file is a part of AddressSanitizer, an address sanity checker.
     11 //
     12 // ASan activation/deactivation logic.
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "asan_activation.h"
     16 #include "asan_allocator.h"
     17 #include "asan_flags.h"
     18 #include "asan_internal.h"
     19 #include "asan_mapping.h"
     20 #include "asan_poisoning.h"
     21 #include "asan_stack.h"
     22 #include "sanitizer_common/sanitizer_common.h"
     23 #include "sanitizer_common/sanitizer_flags.h"
     24 
     25 namespace __asan {
     26 
     27 static struct AsanDeactivatedFlags {
     28   AllocatorOptions allocator_options;
     29   int malloc_context_size;
     30   bool poison_heap;
     31   bool coverage;
     32   const char *coverage_dir;
     33 
     34   void RegisterActivationFlags(FlagParser *parser, Flags *f, CommonFlags *cf) {
     35 #define ASAN_ACTIVATION_FLAG(Type, Name) \
     36   RegisterFlag(parser, #Name, "", &f->Name);
     37 #define COMMON_ACTIVATION_FLAG(Type, Name) \
     38   RegisterFlag(parser, #Name, "", &cf->Name);
     39 #include "asan_activation_flags.inc"
     40 #undef ASAN_ACTIVATION_FLAG
     41 #undef COMMON_ACTIVATION_FLAG
     42 
     43     RegisterIncludeFlags(parser, cf);
     44   }
     45 
     46   void OverrideFromActivationFlags() {
     47     Flags f;
     48     CommonFlags cf;
     49     FlagParser parser;
     50     RegisterActivationFlags(&parser, &f, &cf);
     51 
     52     cf.SetDefaults();
     53     // Copy the current activation flags.
     54     allocator_options.CopyTo(&f, &cf);
     55     cf.malloc_context_size = malloc_context_size;
     56     f.poison_heap = poison_heap;
     57     cf.coverage = coverage;
     58     cf.coverage_dir = coverage_dir;
     59     cf.verbosity = Verbosity();
     60     cf.help = false; // this is activation-specific help
     61 
     62     // Check if activation flags need to be overriden.
     63     if (const char *env = GetEnv("ASAN_ACTIVATION_OPTIONS")) {
     64       parser.ParseString(env);
     65     }
     66 
     67     InitializeCommonFlags(&cf);
     68 
     69     if (Verbosity()) ReportUnrecognizedFlags();
     70 
     71     if (cf.help) parser.PrintFlagDescriptions();
     72 
     73     allocator_options.SetFrom(&f, &cf);
     74     malloc_context_size = cf.malloc_context_size;
     75     poison_heap = f.poison_heap;
     76     coverage = cf.coverage;
     77     coverage_dir = cf.coverage_dir;
     78   }
     79 
     80   void Print() {
     81     Report(
     82         "quarantine_size_mb %d, thread_local_quarantine_size_kb %d, "
     83         "max_redzone %d, poison_heap %d, malloc_context_size %d, "
     84         "alloc_dealloc_mismatch %d, allocator_may_return_null %d, coverage %d, "
     85         "coverage_dir %s, allocator_release_to_os_interval_ms %d\n",
     86         allocator_options.quarantine_size_mb,
     87         allocator_options.thread_local_quarantine_size_kb,
     88         allocator_options.max_redzone, poison_heap, malloc_context_size,
     89         allocator_options.alloc_dealloc_mismatch,
     90         allocator_options.may_return_null, coverage, coverage_dir,
     91         allocator_options.release_to_os_interval_ms);
     92   }
     93 } asan_deactivated_flags;
     94 
     95 static bool asan_is_deactivated;
     96 
     97 void AsanDeactivate() {
     98   CHECK(!asan_is_deactivated);
     99   VReport(1, "Deactivating ASan\n");
    100 
    101   // Stash runtime state.
    102   GetAllocatorOptions(&asan_deactivated_flags.allocator_options);
    103   asan_deactivated_flags.malloc_context_size = GetMallocContextSize();
    104   asan_deactivated_flags.poison_heap = CanPoisonMemory();
    105   asan_deactivated_flags.coverage = common_flags()->coverage;
    106   asan_deactivated_flags.coverage_dir = common_flags()->coverage_dir;
    107 
    108   // Deactivate the runtime.
    109   SetCanPoisonMemory(false);
    110   SetMallocContextSize(1);
    111 
    112   AllocatorOptions disabled = asan_deactivated_flags.allocator_options;
    113   disabled.quarantine_size_mb = 0;
    114   disabled.thread_local_quarantine_size_kb = 0;
    115   // Redzone must be at least Max(16, granularity) bytes long.
    116   disabled.min_redzone = Max(16, (int)SHADOW_GRANULARITY);
    117   disabled.max_redzone = disabled.min_redzone;
    118   disabled.alloc_dealloc_mismatch = false;
    119   disabled.may_return_null = true;
    120   ReInitializeAllocator(disabled);
    121 
    122   asan_is_deactivated = true;
    123 }
    124 
    125 void AsanActivate() {
    126   if (!asan_is_deactivated) return;
    127   VReport(1, "Activating ASan\n");
    128 
    129   UpdateProcessName();
    130 
    131   asan_deactivated_flags.OverrideFromActivationFlags();
    132 
    133   SetCanPoisonMemory(asan_deactivated_flags.poison_heap);
    134   SetMallocContextSize(asan_deactivated_flags.malloc_context_size);
    135   ReInitializeAllocator(asan_deactivated_flags.allocator_options);
    136 
    137   asan_is_deactivated = false;
    138   if (Verbosity()) {
    139     Report("Activated with flags:\n");
    140     asan_deactivated_flags.Print();
    141   }
    142 }
    143 
    144 }  // namespace __asan
    145