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