1217222abSNico Weber //===-- asan_flags.cpp ------------------------------------------*- C++ -*-===// 2217222abSNico Weber // 3217222abSNico Weber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4217222abSNico Weber // See https://llvm.org/LICENSE.txt for license information. 5217222abSNico Weber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6217222abSNico Weber // 7217222abSNico Weber //===----------------------------------------------------------------------===// 8217222abSNico Weber // 9217222abSNico Weber // This file is a part of AddressSanitizer, an address sanity checker. 10217222abSNico Weber // 11217222abSNico Weber // ASan flag parsing logic. 12217222abSNico Weber //===----------------------------------------------------------------------===// 13217222abSNico Weber 140a93e9f2SCharlie Barto #include "asan_flags.h" 1553a81d4dSCharlie Barto 1653a81d4dSCharlie Barto #include "asan_activation.h" 17217222abSNico Weber #include "asan_interface_internal.h" 18217222abSNico Weber #include "asan_stack.h" 19217222abSNico Weber #include "lsan/lsan_common.h" 20217222abSNico Weber #include "sanitizer_common/sanitizer_common.h" 210a93e9f2SCharlie Barto #include "sanitizer_common/sanitizer_flag_parser.h" 2253a81d4dSCharlie Barto #include "sanitizer_common/sanitizer_flags.h" 2353a81d4dSCharlie Barto #include "sanitizer_common/sanitizer_win_interception.h" 24217222abSNico Weber #include "ubsan/ubsan_flags.h" 25217222abSNico Weber #include "ubsan/ubsan_platform.h" 26217222abSNico Weber 27217222abSNico Weber namespace __asan { 28217222abSNico Weber 29217222abSNico Weber Flags asan_flags_dont_use_directly; // use via flags(). 30217222abSNico Weber 31217222abSNico Weber static const char *MaybeUseAsanDefaultOptionsCompileDefinition() { 32217222abSNico Weber #ifdef ASAN_DEFAULT_OPTIONS 33217222abSNico Weber return SANITIZER_STRINGIFY(ASAN_DEFAULT_OPTIONS); 34217222abSNico Weber #else 35217222abSNico Weber return ""; 36217222abSNico Weber #endif 37217222abSNico Weber } 38217222abSNico Weber 39217222abSNico Weber void Flags::SetDefaults() { 40217222abSNico Weber #define ASAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; 41217222abSNico Weber #include "asan_flags.inc" 42217222abSNico Weber #undef ASAN_FLAG 43217222abSNico Weber } 44217222abSNico Weber 45217222abSNico Weber static void RegisterAsanFlags(FlagParser *parser, Flags *f) { 46217222abSNico Weber #define ASAN_FLAG(Type, Name, DefaultValue, Description) \ 47217222abSNico Weber RegisterFlag(parser, #Name, Description, &f->Name); 48217222abSNico Weber #include "asan_flags.inc" 49217222abSNico Weber #undef ASAN_FLAG 50217222abSNico Weber } 51217222abSNico Weber 5253a81d4dSCharlie Barto static void DisplayHelpMessages(FlagParser *parser) { 5353a81d4dSCharlie Barto // TODO(eugenis): dump all flags at verbosity>=2? 5453a81d4dSCharlie Barto if (Verbosity()) { 5553a81d4dSCharlie Barto ReportUnrecognizedFlags(); 5653a81d4dSCharlie Barto } 5753a81d4dSCharlie Barto 5853a81d4dSCharlie Barto if (common_flags()->help) { 5953a81d4dSCharlie Barto parser->PrintFlagDescriptions(); 6053a81d4dSCharlie Barto } 6153a81d4dSCharlie Barto } 6253a81d4dSCharlie Barto 6353a81d4dSCharlie Barto static void InitializeDefaultFlags() { 6453a81d4dSCharlie Barto Flags *f = flags(); 6553a81d4dSCharlie Barto FlagParser asan_parser; 6653a81d4dSCharlie Barto 67217222abSNico Weber // Set the default values and prepare for parsing ASan and common flags. 68217222abSNico Weber SetCommonFlagsDefaults(); 69217222abSNico Weber { 70217222abSNico Weber CommonFlags cf; 71217222abSNico Weber cf.CopyFrom(*common_flags()); 72217222abSNico Weber cf.detect_leaks = cf.detect_leaks && CAN_SANITIZE_LEAKS; 73217222abSNico Weber cf.external_symbolizer_path = GetEnv("ASAN_SYMBOLIZER_PATH"); 74217222abSNico Weber cf.malloc_context_size = kDefaultMallocContextSize; 75217222abSNico Weber cf.intercept_tls_get_addr = true; 76217222abSNico Weber cf.exitcode = 1; 77217222abSNico Weber OverrideCommonFlags(cf); 78217222abSNico Weber } 79217222abSNico Weber f->SetDefaults(); 80217222abSNico Weber 81217222abSNico Weber RegisterAsanFlags(&asan_parser, f); 82217222abSNico Weber RegisterCommonFlags(&asan_parser); 83217222abSNico Weber 84217222abSNico Weber // Set the default values and prepare for parsing LSan and UBSan flags 85217222abSNico Weber // (which can also overwrite common flags). 86217222abSNico Weber #if CAN_SANITIZE_LEAKS 87217222abSNico Weber __lsan::Flags *lf = __lsan::flags(); 88217222abSNico Weber lf->SetDefaults(); 89217222abSNico Weber 90217222abSNico Weber FlagParser lsan_parser; 91217222abSNico Weber __lsan::RegisterLsanFlags(&lsan_parser, lf); 92217222abSNico Weber RegisterCommonFlags(&lsan_parser); 93217222abSNico Weber #endif 94217222abSNico Weber 95217222abSNico Weber #if CAN_SANITIZE_UB 96217222abSNico Weber __ubsan::Flags *uf = __ubsan::flags(); 97217222abSNico Weber uf->SetDefaults(); 98217222abSNico Weber 99217222abSNico Weber FlagParser ubsan_parser; 100217222abSNico Weber __ubsan::RegisterUbsanFlags(&ubsan_parser, uf); 101217222abSNico Weber RegisterCommonFlags(&ubsan_parser); 102217222abSNico Weber #endif 103217222abSNico Weber 1048246b2e1SMariusz Borsa if (SANITIZER_APPLE) { 105217222abSNico Weber // Support macOS MallocScribble and MallocPreScribble: 106217222abSNico Weber // <https://developer.apple.com/library/content/documentation/Performance/ 107217222abSNico Weber // Conceptual/ManagingMemory/Articles/MallocDebug.html> 108217222abSNico Weber if (GetEnv("MallocScribble")) { 109217222abSNico Weber f->max_free_fill_size = 0x1000; 110217222abSNico Weber } 111217222abSNico Weber if (GetEnv("MallocPreScribble")) { 112217222abSNico Weber f->malloc_fill_byte = 0xaa; 113217222abSNico Weber } 114217222abSNico Weber } 115217222abSNico Weber 116217222abSNico Weber // Override from ASan compile definition. 117217222abSNico Weber const char *asan_compile_def = MaybeUseAsanDefaultOptionsCompileDefinition(); 118217222abSNico Weber asan_parser.ParseString(asan_compile_def); 119217222abSNico Weber 120217222abSNico Weber // Override from user-specified string. 1212d7fd38cSFangrui Song const char *asan_default_options = __asan_default_options(); 122217222abSNico Weber asan_parser.ParseString(asan_default_options); 123217222abSNico Weber #if CAN_SANITIZE_UB 1242d7fd38cSFangrui Song const char *ubsan_default_options = __ubsan_default_options(); 125217222abSNico Weber ubsan_parser.ParseString(ubsan_default_options); 126217222abSNico Weber #endif 127217222abSNico Weber #if CAN_SANITIZE_LEAKS 1282d7fd38cSFangrui Song const char *lsan_default_options = __lsan_default_options(); 129217222abSNico Weber lsan_parser.ParseString(lsan_default_options); 130217222abSNico Weber #endif 131217222abSNico Weber 132217222abSNico Weber // Override from command line. 133217222abSNico Weber asan_parser.ParseStringFromEnv("ASAN_OPTIONS"); 134217222abSNico Weber #if CAN_SANITIZE_LEAKS 135217222abSNico Weber lsan_parser.ParseStringFromEnv("LSAN_OPTIONS"); 136217222abSNico Weber #endif 137217222abSNico Weber #if CAN_SANITIZE_UB 138217222abSNico Weber ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS"); 139217222abSNico Weber #endif 140217222abSNico Weber 141217222abSNico Weber InitializeCommonFlags(); 142217222abSNico Weber 1430a93e9f2SCharlie Barto // TODO(samsonov): print all of the flags (ASan, LSan, common). 14453a81d4dSCharlie Barto DisplayHelpMessages(&asan_parser); 1450a93e9f2SCharlie Barto } 1468fa66c6cSCharlie Barto 14753a81d4dSCharlie Barto static void ProcessFlags() { 14853a81d4dSCharlie Barto Flags *f = flags(); 14953a81d4dSCharlie Barto 150217222abSNico Weber // Flag validation: 151217222abSNico Weber if (!CAN_SANITIZE_LEAKS && common_flags()->detect_leaks) { 152217222abSNico Weber Report("%s: detect_leaks is not supported on this platform.\n", 153217222abSNico Weber SanitizerToolName); 154217222abSNico Weber Die(); 155217222abSNico Weber } 156ad56941aSKirill Stoimenov // Ensure that redzone is at least ASAN_SHADOW_GRANULARITY. 157ad56941aSKirill Stoimenov if (f->redzone < (int)ASAN_SHADOW_GRANULARITY) 158ad56941aSKirill Stoimenov f->redzone = ASAN_SHADOW_GRANULARITY; 159217222abSNico Weber // Make "strict_init_order" imply "check_initialization_order". 160217222abSNico Weber // TODO(samsonov): Use a single runtime flag for an init-order checker. 161217222abSNico Weber if (f->strict_init_order) { 162217222abSNico Weber f->check_initialization_order = true; 163217222abSNico Weber } 164217222abSNico Weber CHECK_LE((uptr)common_flags()->malloc_context_size, kStackTraceMax); 165217222abSNico Weber CHECK_LE(f->min_uar_stack_size_log, f->max_uar_stack_size_log); 166217222abSNico Weber CHECK_GE(f->redzone, 16); 167217222abSNico Weber CHECK_GE(f->max_redzone, f->redzone); 168217222abSNico Weber CHECK_LE(f->max_redzone, 2048); 169217222abSNico Weber CHECK(IsPowerOfTwo(f->redzone)); 170217222abSNico Weber CHECK(IsPowerOfTwo(f->max_redzone)); 171217222abSNico Weber 172217222abSNico Weber // quarantine_size is deprecated but we still honor it. 173217222abSNico Weber // quarantine_size can not be used together with quarantine_size_mb. 174217222abSNico Weber if (f->quarantine_size >= 0 && f->quarantine_size_mb >= 0) { 175217222abSNico Weber Report("%s: please use either 'quarantine_size' (deprecated) or " 176217222abSNico Weber "quarantine_size_mb, but not both\n", SanitizerToolName); 177217222abSNico Weber Die(); 178217222abSNico Weber } 179217222abSNico Weber if (f->quarantine_size >= 0) 180217222abSNico Weber f->quarantine_size_mb = f->quarantine_size >> 20; 181217222abSNico Weber if (f->quarantine_size_mb < 0) { 182217222abSNico Weber const int kDefaultQuarantineSizeMb = 183217222abSNico Weber (ASAN_LOW_MEMORY) ? 1UL << 4 : 1UL << 8; 184217222abSNico Weber f->quarantine_size_mb = kDefaultQuarantineSizeMb; 185217222abSNico Weber } 186217222abSNico Weber if (f->thread_local_quarantine_size_kb < 0) { 187217222abSNico Weber const u32 kDefaultThreadLocalQuarantineSizeKb = 188217222abSNico Weber // It is not advised to go lower than 64Kb, otherwise quarantine batches 189217222abSNico Weber // pushed from thread local quarantine to global one will create too 190217222abSNico Weber // much overhead. One quarantine batch size is 8Kb and it holds up to 191217222abSNico Weber // 1021 chunk, which amounts to 1/8 memory overhead per batch when 192217222abSNico Weber // thread local quarantine is set to 64Kb. 193217222abSNico Weber (ASAN_LOW_MEMORY) ? 1 << 6 : FIRST_32_SECOND_64(1 << 8, 1 << 10); 194217222abSNico Weber f->thread_local_quarantine_size_kb = kDefaultThreadLocalQuarantineSizeKb; 195217222abSNico Weber } 196217222abSNico Weber if (f->thread_local_quarantine_size_kb == 0 && f->quarantine_size_mb > 0) { 197217222abSNico Weber Report("%s: thread_local_quarantine_size_kb can be set to 0 only when " 198217222abSNico Weber "quarantine_size_mb is set to 0\n", SanitizerToolName); 199217222abSNico Weber Die(); 200217222abSNico Weber } 201217222abSNico Weber if (!f->replace_str && common_flags()->intercept_strlen) { 202217222abSNico Weber Report("WARNING: strlen interceptor is enabled even though replace_str=0. " 203217222abSNico Weber "Use intercept_strlen=0 to disable it."); 204217222abSNico Weber } 205217222abSNico Weber if (!f->replace_str && common_flags()->intercept_strchr) { 206217222abSNico Weber Report("WARNING: strchr* interceptors are enabled even though " 207217222abSNico Weber "replace_str=0. Use intercept_strchr=0 to disable them."); 208217222abSNico Weber } 209217222abSNico Weber if (!f->replace_str && common_flags()->intercept_strndup) { 210217222abSNico Weber Report("WARNING: strndup* interceptors are enabled even though " 211217222abSNico Weber "replace_str=0. Use intercept_strndup=0 to disable them."); 212217222abSNico Weber } 213217222abSNico Weber } 214217222abSNico Weber 21553a81d4dSCharlie Barto void InitializeFlags() { 21653a81d4dSCharlie Barto InitializeDefaultFlags(); 21753a81d4dSCharlie Barto ProcessFlags(); 21853a81d4dSCharlie Barto 21953a81d4dSCharlie Barto #if SANITIZER_WINDOWS 22053a81d4dSCharlie Barto // On Windows, weak symbols are emulated by having the user program 22153a81d4dSCharlie Barto // register which weak functions are defined. 22253a81d4dSCharlie Barto // The ASAN DLL will initialize flags prior to user module initialization, 22353a81d4dSCharlie Barto // so __asan_default_options will not point to the user definition yet. 22453a81d4dSCharlie Barto // We still want to ensure we capture when options are passed via 22553a81d4dSCharlie Barto // __asan_default_options, so we add a callback to be run 22653a81d4dSCharlie Barto // when it is registered with the runtime. 22753a81d4dSCharlie Barto 22853a81d4dSCharlie Barto // There is theoretically time between the initial ProcessFlags and 22953a81d4dSCharlie Barto // registering the weak callback where a weak function could be added and we 23053a81d4dSCharlie Barto // would miss it, but in practice, InitializeFlags will always happen under 23153a81d4dSCharlie Barto // the loader lock (if built as a DLL) and so will any calls to 23253a81d4dSCharlie Barto // __sanitizer_register_weak_function. 23353a81d4dSCharlie Barto AddRegisterWeakFunctionCallback( 23453a81d4dSCharlie Barto reinterpret_cast<uptr>(__asan_default_options), []() { 23553a81d4dSCharlie Barto FlagParser asan_parser; 23653a81d4dSCharlie Barto 23753a81d4dSCharlie Barto RegisterAsanFlags(&asan_parser, flags()); 23853a81d4dSCharlie Barto RegisterCommonFlags(&asan_parser); 23953a81d4dSCharlie Barto asan_parser.ParseString(__asan_default_options()); 24053a81d4dSCharlie Barto 24153a81d4dSCharlie Barto DisplayHelpMessages(&asan_parser); 24253a81d4dSCharlie Barto ProcessFlags(); 243*2dc22615SDavid Justo 244*2dc22615SDavid Justo // TODO: Update other globals and data structures that may need to change 245*2dc22615SDavid Justo // after initialization due to new flags potentially being set changing after 246*2dc22615SDavid Justo // `__asan_default_options` is registered. 247*2dc22615SDavid Justo // See GH issue 'https://github.com/llvm/llvm-project/issues/117925' for 248*2dc22615SDavid Justo // details. 249*2dc22615SDavid Justo SetAllocatorMayReturnNull(common_flags()->allocator_may_return_null); 25053a81d4dSCharlie Barto }); 25153a81d4dSCharlie Barto 25253a81d4dSCharlie Barto # if CAN_SANITIZE_UB 25353a81d4dSCharlie Barto AddRegisterWeakFunctionCallback( 25453a81d4dSCharlie Barto reinterpret_cast<uptr>(__ubsan_default_options), []() { 25553a81d4dSCharlie Barto FlagParser ubsan_parser; 25653a81d4dSCharlie Barto 25753a81d4dSCharlie Barto __ubsan::RegisterUbsanFlags(&ubsan_parser, __ubsan::flags()); 25853a81d4dSCharlie Barto RegisterCommonFlags(&ubsan_parser); 25953a81d4dSCharlie Barto ubsan_parser.ParseString(__ubsan_default_options()); 26053a81d4dSCharlie Barto 26153a81d4dSCharlie Barto // To match normal behavior, do not print UBSan help. 26253a81d4dSCharlie Barto ProcessFlags(); 26353a81d4dSCharlie Barto }); 26453a81d4dSCharlie Barto # endif 26553a81d4dSCharlie Barto 26653a81d4dSCharlie Barto # if CAN_SANITIZE_LEAKS 26753a81d4dSCharlie Barto AddRegisterWeakFunctionCallback( 26853a81d4dSCharlie Barto reinterpret_cast<uptr>(__lsan_default_options), []() { 26953a81d4dSCharlie Barto FlagParser lsan_parser; 27053a81d4dSCharlie Barto 27153a81d4dSCharlie Barto __lsan::RegisterLsanFlags(&lsan_parser, __lsan::flags()); 27253a81d4dSCharlie Barto RegisterCommonFlags(&lsan_parser); 27353a81d4dSCharlie Barto lsan_parser.ParseString(__lsan_default_options()); 27453a81d4dSCharlie Barto 27553a81d4dSCharlie Barto // To match normal behavior, do not print LSan help. 27653a81d4dSCharlie Barto ProcessFlags(); 27753a81d4dSCharlie Barto }); 27853a81d4dSCharlie Barto # endif 27953a81d4dSCharlie Barto 28053a81d4dSCharlie Barto #endif 28153a81d4dSCharlie Barto } 28253a81d4dSCharlie Barto 283217222abSNico Weber } // namespace __asan 284217222abSNico Weber 285217222abSNico Weber SANITIZER_INTERFACE_WEAK_DEF(const char*, __asan_default_options, void) { 286217222abSNico Weber return ""; 287217222abSNico Weber } 288