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