1 //===-- asan_flags.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 flag parsing logic. 12 //===----------------------------------------------------------------------===// 13 14 #include "asan_activation.h" 15 #include "asan_flags.h" 16 #include "asan_interface_internal.h" 17 #include "asan_stack.h" 18 #include "lsan/lsan_common.h" 19 #include "sanitizer_common/sanitizer_common.h" 20 #include "sanitizer_common/sanitizer_flags.h" 21 #include "sanitizer_common/sanitizer_flag_parser.h" 22 #include "ubsan/ubsan_flags.h" 23 #include "ubsan/ubsan_platform.h" 24 25 namespace __asan { 26 27 Flags asan_flags_dont_use_directly; // use via flags(). 28 29 static const char *MaybeUseAsanDefaultOptionsCompileDefinition() { 30 #ifdef ASAN_DEFAULT_OPTIONS 31 return SANITIZER_STRINGIFY(ASAN_DEFAULT_OPTIONS); 32 #else 33 return ""; 34 #endif 35 } 36 37 void Flags::SetDefaults() { 38 #define ASAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; 39 #include "asan_flags.inc" 40 #undef ASAN_FLAG 41 } 42 43 static void RegisterAsanFlags(FlagParser *parser, Flags *f) { 44 #define ASAN_FLAG(Type, Name, DefaultValue, Description) \ 45 RegisterFlag(parser, #Name, Description, &f->Name); 46 #include "asan_flags.inc" 47 #undef ASAN_FLAG 48 } 49 50 void InitializeFlags() { 51 // Set the default values and prepare for parsing ASan and common flags. 52 SetCommonFlagsDefaults(); 53 { 54 CommonFlags cf; 55 cf.CopyFrom(*common_flags()); 56 cf.detect_leaks = cf.detect_leaks && CAN_SANITIZE_LEAKS; 57 cf.external_symbolizer_path = GetEnv("ASAN_SYMBOLIZER_PATH"); 58 cf.malloc_context_size = kDefaultMallocContextSize; 59 cf.intercept_tls_get_addr = true; 60 cf.exitcode = 1; 61 OverrideCommonFlags(cf); 62 } 63 Flags *f = flags(); 64 f->SetDefaults(); 65 66 FlagParser asan_parser; 67 RegisterAsanFlags(&asan_parser, f); 68 RegisterCommonFlags(&asan_parser); 69 70 // Set the default values and prepare for parsing LSan and UBSan flags 71 // (which can also overwrite common flags). 72 #if CAN_SANITIZE_LEAKS 73 __lsan::Flags *lf = __lsan::flags(); 74 lf->SetDefaults(); 75 76 FlagParser lsan_parser; 77 __lsan::RegisterLsanFlags(&lsan_parser, lf); 78 RegisterCommonFlags(&lsan_parser); 79 #endif 80 81 #if CAN_SANITIZE_UB 82 __ubsan::Flags *uf = __ubsan::flags(); 83 uf->SetDefaults(); 84 85 FlagParser ubsan_parser; 86 __ubsan::RegisterUbsanFlags(&ubsan_parser, uf); 87 RegisterCommonFlags(&ubsan_parser); 88 #endif 89 90 if (SANITIZER_APPLE) { 91 // Support macOS MallocScribble and MallocPreScribble: 92 // <https://developer.apple.com/library/content/documentation/Performance/ 93 // Conceptual/ManagingMemory/Articles/MallocDebug.html> 94 if (GetEnv("MallocScribble")) { 95 f->max_free_fill_size = 0x1000; 96 } 97 if (GetEnv("MallocPreScribble")) { 98 f->malloc_fill_byte = 0xaa; 99 } 100 } 101 102 // Override from ASan compile definition. 103 const char *asan_compile_def = MaybeUseAsanDefaultOptionsCompileDefinition(); 104 asan_parser.ParseString(asan_compile_def); 105 106 // Override from user-specified string. 107 const char *asan_default_options = __asan_default_options(); 108 asan_parser.ParseString(asan_default_options); 109 #if CAN_SANITIZE_UB 110 const char *ubsan_default_options = __ubsan_default_options(); 111 ubsan_parser.ParseString(ubsan_default_options); 112 #endif 113 #if CAN_SANITIZE_LEAKS 114 const char *lsan_default_options = __lsan_default_options(); 115 lsan_parser.ParseString(lsan_default_options); 116 #endif 117 118 // Override from command line. 119 asan_parser.ParseStringFromEnv("ASAN_OPTIONS"); 120 #if CAN_SANITIZE_LEAKS 121 lsan_parser.ParseStringFromEnv("LSAN_OPTIONS"); 122 #endif 123 #if CAN_SANITIZE_UB 124 ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS"); 125 #endif 126 127 InitializeCommonFlags(); 128 129 // TODO(eugenis): dump all flags at verbosity>=2? 130 if (Verbosity()) ReportUnrecognizedFlags(); 131 132 if (common_flags()->help) { 133 // TODO(samsonov): print all of the flags (ASan, LSan, common). 134 asan_parser.PrintFlagDescriptions(); 135 } 136 137 // Flag validation: 138 if (!CAN_SANITIZE_LEAKS && common_flags()->detect_leaks) { 139 Report("%s: detect_leaks is not supported on this platform.\n", 140 SanitizerToolName); 141 Die(); 142 } 143 // Ensure that redzone is at least ASAN_SHADOW_GRANULARITY. 144 if (f->redzone < (int)ASAN_SHADOW_GRANULARITY) 145 f->redzone = ASAN_SHADOW_GRANULARITY; 146 // Make "strict_init_order" imply "check_initialization_order". 147 // TODO(samsonov): Use a single runtime flag for an init-order checker. 148 if (f->strict_init_order) { 149 f->check_initialization_order = true; 150 } 151 CHECK_LE((uptr)common_flags()->malloc_context_size, kStackTraceMax); 152 CHECK_LE(f->min_uar_stack_size_log, f->max_uar_stack_size_log); 153 CHECK_GE(f->redzone, 16); 154 CHECK_GE(f->max_redzone, f->redzone); 155 CHECK_LE(f->max_redzone, 2048); 156 CHECK(IsPowerOfTwo(f->redzone)); 157 CHECK(IsPowerOfTwo(f->max_redzone)); 158 159 // quarantine_size is deprecated but we still honor it. 160 // quarantine_size can not be used together with quarantine_size_mb. 161 if (f->quarantine_size >= 0 && f->quarantine_size_mb >= 0) { 162 Report("%s: please use either 'quarantine_size' (deprecated) or " 163 "quarantine_size_mb, but not both\n", SanitizerToolName); 164 Die(); 165 } 166 if (f->quarantine_size >= 0) 167 f->quarantine_size_mb = f->quarantine_size >> 20; 168 if (f->quarantine_size_mb < 0) { 169 const int kDefaultQuarantineSizeMb = 170 (ASAN_LOW_MEMORY) ? 1UL << 4 : 1UL << 8; 171 f->quarantine_size_mb = kDefaultQuarantineSizeMb; 172 } 173 if (f->thread_local_quarantine_size_kb < 0) { 174 const u32 kDefaultThreadLocalQuarantineSizeKb = 175 // It is not advised to go lower than 64Kb, otherwise quarantine batches 176 // pushed from thread local quarantine to global one will create too 177 // much overhead. One quarantine batch size is 8Kb and it holds up to 178 // 1021 chunk, which amounts to 1/8 memory overhead per batch when 179 // thread local quarantine is set to 64Kb. 180 (ASAN_LOW_MEMORY) ? 1 << 6 : FIRST_32_SECOND_64(1 << 8, 1 << 10); 181 f->thread_local_quarantine_size_kb = kDefaultThreadLocalQuarantineSizeKb; 182 } 183 if (f->thread_local_quarantine_size_kb == 0 && f->quarantine_size_mb > 0) { 184 Report("%s: thread_local_quarantine_size_kb can be set to 0 only when " 185 "quarantine_size_mb is set to 0\n", SanitizerToolName); 186 Die(); 187 } 188 if (!f->replace_str && common_flags()->intercept_strlen) { 189 Report("WARNING: strlen interceptor is enabled even though replace_str=0. " 190 "Use intercept_strlen=0 to disable it."); 191 } 192 if (!f->replace_str && common_flags()->intercept_strchr) { 193 Report("WARNING: strchr* interceptors are enabled even though " 194 "replace_str=0. Use intercept_strchr=0 to disable them."); 195 } 196 if (!f->replace_str && common_flags()->intercept_strndup) { 197 Report("WARNING: strndup* interceptors are enabled even though " 198 "replace_str=0. Use intercept_strndup=0 to disable them."); 199 } 200 } 201 202 } // namespace __asan 203 204 SANITIZER_INTERFACE_WEAK_DEF(const char*, __asan_default_options, void) { 205 return ""; 206 } 207