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_flags.h" 15 16 #include "asan_activation.h" 17 #include "asan_interface_internal.h" 18 #include "asan_stack.h" 19 #include "lsan/lsan_common.h" 20 #include "sanitizer_common/sanitizer_common.h" 21 #include "sanitizer_common/sanitizer_flag_parser.h" 22 #include "sanitizer_common/sanitizer_flags.h" 23 #include "sanitizer_common/sanitizer_win_interception.h" 24 #include "ubsan/ubsan_flags.h" 25 #include "ubsan/ubsan_platform.h" 26 27 namespace __asan { 28 29 Flags asan_flags_dont_use_directly; // use via flags(). 30 31 static const char *MaybeUseAsanDefaultOptionsCompileDefinition() { 32 #ifdef ASAN_DEFAULT_OPTIONS 33 return SANITIZER_STRINGIFY(ASAN_DEFAULT_OPTIONS); 34 #else 35 return ""; 36 #endif 37 } 38 39 void Flags::SetDefaults() { 40 #define ASAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; 41 #include "asan_flags.inc" 42 #undef ASAN_FLAG 43 } 44 45 static void RegisterAsanFlags(FlagParser *parser, Flags *f) { 46 #define ASAN_FLAG(Type, Name, DefaultValue, Description) \ 47 RegisterFlag(parser, #Name, Description, &f->Name); 48 #include "asan_flags.inc" 49 #undef ASAN_FLAG 50 } 51 52 static void DisplayHelpMessages(FlagParser *parser) { 53 // TODO(eugenis): dump all flags at verbosity>=2? 54 if (Verbosity()) { 55 ReportUnrecognizedFlags(); 56 } 57 58 if (common_flags()->help) { 59 parser->PrintFlagDescriptions(); 60 } 61 } 62 63 static void InitializeDefaultFlags() { 64 Flags *f = flags(); 65 FlagParser asan_parser; 66 67 // Set the default values and prepare for parsing ASan and common flags. 68 SetCommonFlagsDefaults(); 69 { 70 CommonFlags cf; 71 cf.CopyFrom(*common_flags()); 72 cf.detect_leaks = cf.detect_leaks && CAN_SANITIZE_LEAKS; 73 cf.external_symbolizer_path = GetEnv("ASAN_SYMBOLIZER_PATH"); 74 cf.malloc_context_size = kDefaultMallocContextSize; 75 cf.intercept_tls_get_addr = true; 76 cf.exitcode = 1; 77 OverrideCommonFlags(cf); 78 } 79 f->SetDefaults(); 80 81 RegisterAsanFlags(&asan_parser, f); 82 RegisterCommonFlags(&asan_parser); 83 84 // Set the default values and prepare for parsing LSan and UBSan flags 85 // (which can also overwrite common flags). 86 #if CAN_SANITIZE_LEAKS 87 __lsan::Flags *lf = __lsan::flags(); 88 lf->SetDefaults(); 89 90 FlagParser lsan_parser; 91 __lsan::RegisterLsanFlags(&lsan_parser, lf); 92 RegisterCommonFlags(&lsan_parser); 93 #endif 94 95 #if CAN_SANITIZE_UB 96 __ubsan::Flags *uf = __ubsan::flags(); 97 uf->SetDefaults(); 98 99 FlagParser ubsan_parser; 100 __ubsan::RegisterUbsanFlags(&ubsan_parser, uf); 101 RegisterCommonFlags(&ubsan_parser); 102 #endif 103 104 if (SANITIZER_APPLE) { 105 // Support macOS MallocScribble and MallocPreScribble: 106 // <https://developer.apple.com/library/content/documentation/Performance/ 107 // Conceptual/ManagingMemory/Articles/MallocDebug.html> 108 if (GetEnv("MallocScribble")) { 109 f->max_free_fill_size = 0x1000; 110 } 111 if (GetEnv("MallocPreScribble")) { 112 f->malloc_fill_byte = 0xaa; 113 } 114 } 115 116 // Override from ASan compile definition. 117 const char *asan_compile_def = MaybeUseAsanDefaultOptionsCompileDefinition(); 118 asan_parser.ParseString(asan_compile_def); 119 120 // Override from user-specified string. 121 const char *asan_default_options = __asan_default_options(); 122 asan_parser.ParseString(asan_default_options); 123 #if CAN_SANITIZE_UB 124 const char *ubsan_default_options = __ubsan_default_options(); 125 ubsan_parser.ParseString(ubsan_default_options); 126 #endif 127 #if CAN_SANITIZE_LEAKS 128 const char *lsan_default_options = __lsan_default_options(); 129 lsan_parser.ParseString(lsan_default_options); 130 #endif 131 132 // Override from command line. 133 asan_parser.ParseStringFromEnv("ASAN_OPTIONS"); 134 #if CAN_SANITIZE_LEAKS 135 lsan_parser.ParseStringFromEnv("LSAN_OPTIONS"); 136 #endif 137 #if CAN_SANITIZE_UB 138 ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS"); 139 #endif 140 141 InitializeCommonFlags(); 142 143 // TODO(samsonov): print all of the flags (ASan, LSan, common). 144 DisplayHelpMessages(&asan_parser); 145 } 146 147 // Validate flags and report incompatible configurations 148 static void ProcessFlags() { 149 Flags *f = flags(); 150 151 // Flag validation: 152 if (!CAN_SANITIZE_LEAKS && common_flags()->detect_leaks) { 153 Report("%s: detect_leaks is not supported on this platform.\n", 154 SanitizerToolName); 155 Die(); 156 } 157 // Ensure that redzone is at least ASAN_SHADOW_GRANULARITY. 158 if (f->redzone < (int)ASAN_SHADOW_GRANULARITY) 159 f->redzone = ASAN_SHADOW_GRANULARITY; 160 // Make "strict_init_order" imply "check_initialization_order". 161 // TODO(samsonov): Use a single runtime flag for an init-order checker. 162 if (f->strict_init_order) { 163 f->check_initialization_order = true; 164 } 165 CHECK_LE((uptr)common_flags()->malloc_context_size, kStackTraceMax); 166 CHECK_LE(f->min_uar_stack_size_log, f->max_uar_stack_size_log); 167 CHECK_GE(f->redzone, 16); 168 CHECK_GE(f->max_redzone, f->redzone); 169 CHECK_LE(f->max_redzone, 2048); 170 CHECK(IsPowerOfTwo(f->redzone)); 171 CHECK(IsPowerOfTwo(f->max_redzone)); 172 173 // quarantine_size is deprecated but we still honor it. 174 // quarantine_size can not be used together with quarantine_size_mb. 175 if (f->quarantine_size >= 0 && f->quarantine_size_mb >= 0) { 176 Report("%s: please use either 'quarantine_size' (deprecated) or " 177 "quarantine_size_mb, but not both\n", SanitizerToolName); 178 Die(); 179 } 180 if (f->quarantine_size >= 0) 181 f->quarantine_size_mb = f->quarantine_size >> 20; 182 if (f->quarantine_size_mb < 0) { 183 const int kDefaultQuarantineSizeMb = 184 (ASAN_LOW_MEMORY) ? 1UL << 4 : 1UL << 8; 185 f->quarantine_size_mb = kDefaultQuarantineSizeMb; 186 } 187 if (f->thread_local_quarantine_size_kb < 0) { 188 const u32 kDefaultThreadLocalQuarantineSizeKb = 189 // It is not advised to go lower than 64Kb, otherwise quarantine batches 190 // pushed from thread local quarantine to global one will create too 191 // much overhead. One quarantine batch size is 8Kb and it holds up to 192 // 1021 chunk, which amounts to 1/8 memory overhead per batch when 193 // thread local quarantine is set to 64Kb. 194 (ASAN_LOW_MEMORY) ? 1 << 6 : FIRST_32_SECOND_64(1 << 8, 1 << 10); 195 f->thread_local_quarantine_size_kb = kDefaultThreadLocalQuarantineSizeKb; 196 } 197 if (f->thread_local_quarantine_size_kb == 0 && f->quarantine_size_mb > 0) { 198 Report("%s: thread_local_quarantine_size_kb can be set to 0 only when " 199 "quarantine_size_mb is set to 0\n", SanitizerToolName); 200 Die(); 201 } 202 if (!f->replace_str && common_flags()->intercept_strlen) { 203 Report("WARNING: strlen interceptor is enabled even though replace_str=0. " 204 "Use intercept_strlen=0 to disable it."); 205 } 206 if (!f->replace_str && common_flags()->intercept_strchr) { 207 Report("WARNING: strchr* interceptors are enabled even though " 208 "replace_str=0. Use intercept_strchr=0 to disable them."); 209 } 210 if (!f->replace_str && common_flags()->intercept_strndup) { 211 Report("WARNING: strndup* interceptors are enabled even though " 212 "replace_str=0. Use intercept_strndup=0 to disable them."); 213 } 214 } 215 216 void InitializeFlags() { 217 InitializeDefaultFlags(); 218 ProcessFlags(); 219 220 #if SANITIZER_WINDOWS 221 // On Windows, weak symbols (such as the `__asan_default_options` function) 222 // are emulated by having the user program register which weak functions are 223 // defined. The ASAN DLL will initialize flags prior to user module 224 // initialization, so __asan_default_options will not point to the user 225 // definition yet. We still want to ensure we capture when options are passed 226 // via 227 // __asan_default_options, so we add a callback to be run 228 // when it is registered with the runtime. 229 230 // There is theoretically time between the initial ProcessFlags and 231 // registering the weak callback where a weak function could be added and we 232 // would miss it, but in practice, InitializeFlags will always happen under 233 // the loader lock (if built as a DLL) and so will any calls to 234 // __sanitizer_register_weak_function. 235 AddRegisterWeakFunctionCallback( 236 reinterpret_cast<uptr>(__asan_default_options), []() { 237 // We call `InitializeDefaultFlags` again, instead of just parsing 238 // `__asan_default_options` directly, to ensure that flags set through 239 // `ASAN_OPTS` take precedence over those set through 240 // `__asan_default_options`. 241 InitializeDefaultFlags(); 242 ProcessFlags(); 243 ApplyFlags(); 244 }); 245 246 # if CAN_SANITIZE_UB 247 AddRegisterWeakFunctionCallback( 248 reinterpret_cast<uptr>(__ubsan_default_options), []() { 249 FlagParser ubsan_parser; 250 251 __ubsan::RegisterUbsanFlags(&ubsan_parser, __ubsan::flags()); 252 RegisterCommonFlags(&ubsan_parser); 253 ubsan_parser.ParseString(__ubsan_default_options()); 254 255 // To match normal behavior, do not print UBSan help. 256 ProcessFlags(); 257 }); 258 # endif 259 260 # if CAN_SANITIZE_LEAKS 261 AddRegisterWeakFunctionCallback( 262 reinterpret_cast<uptr>(__lsan_default_options), []() { 263 FlagParser lsan_parser; 264 265 __lsan::RegisterLsanFlags(&lsan_parser, __lsan::flags()); 266 RegisterCommonFlags(&lsan_parser); 267 lsan_parser.ParseString(__lsan_default_options()); 268 269 // To match normal behavior, do not print LSan help. 270 ProcessFlags(); 271 }); 272 # endif 273 274 #endif 275 } 276 277 } // namespace __asan 278 279 SANITIZER_INTERFACE_WEAK_DEF(const char*, __asan_default_options, void) { 280 return ""; 281 } 282