diff options
Diffstat (limited to 'lib/asan/asan_rtl.cc')
-rw-r--r-- | lib/asan/asan_rtl.cc | 125 |
1 files changed, 62 insertions, 63 deletions
diff --git a/lib/asan/asan_rtl.cc b/lib/asan/asan_rtl.cc index f989c5c0d2a5..11f05954d31e 100644 --- a/lib/asan/asan_rtl.cc +++ b/lib/asan/asan_rtl.cc @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "asan_allocator.h" #include "asan_interceptors.h" +#include "asan_interface_internal.h" #include "asan_internal.h" #include "asan_mapping.h" #include "asan_poisoning.h" @@ -26,6 +27,8 @@ #include "sanitizer_common/sanitizer_symbolizer.h" #include "lsan/lsan_common.h" +int __asan_option_detect_stack_use_after_return; // Global interface symbol. + namespace __asan { uptr AsanMappingProfile[kAsanMappingProfileSize]; @@ -89,7 +92,6 @@ static void ParseFlagsFromString(Flags *f, const char *str) { CHECK((uptr)common_flags()->malloc_context_size <= kStackTraceMax); ParseFlag(str, &f->quarantine_size, "quarantine_size"); - ParseFlag(str, &f->verbosity, "verbosity"); ParseFlag(str, &f->redzone, "redzone"); CHECK_GE(f->redzone, 16); CHECK(IsPowerOfTwo(f->redzone)); @@ -101,7 +103,9 @@ static void ParseFlagsFromString(Flags *f, const char *str) { ParseFlag(str, &f->replace_str, "replace_str"); ParseFlag(str, &f->replace_intrin, "replace_intrin"); ParseFlag(str, &f->mac_ignore_invalid_free, "mac_ignore_invalid_free"); - ParseFlag(str, &f->use_fake_stack, "use_fake_stack"); + ParseFlag(str, &f->detect_stack_use_after_return, + "detect_stack_use_after_return"); + ParseFlag(str, &f->uar_stack_size_log, "uar_stack_size_log"); ParseFlag(str, &f->max_malloc_fill_size, "max_malloc_fill_size"); ParseFlag(str, &f->malloc_fill_byte, "malloc_fill_byte"); ParseFlag(str, &f->exitcode, "exitcode"); @@ -116,30 +120,25 @@ static void ParseFlagsFromString(Flags *f, const char *str) { ParseFlag(str, &f->print_stats, "print_stats"); ParseFlag(str, &f->print_legend, "print_legend"); ParseFlag(str, &f->atexit, "atexit"); + ParseFlag(str, &f->coverage, "coverage"); ParseFlag(str, &f->disable_core, "disable_core"); ParseFlag(str, &f->allow_reexec, "allow_reexec"); ParseFlag(str, &f->print_full_thread_history, "print_full_thread_history"); - ParseFlag(str, &f->log_path, "log_path"); ParseFlag(str, &f->poison_heap, "poison_heap"); + ParseFlag(str, &f->poison_partial, "poison_partial"); ParseFlag(str, &f->alloc_dealloc_mismatch, "alloc_dealloc_mismatch"); - ParseFlag(str, &f->use_stack_depot, "use_stack_depot"); ParseFlag(str, &f->strict_memcmp, "strict_memcmp"); ParseFlag(str, &f->strict_init_order, "strict_init_order"); - ParseFlag(str, &f->detect_leaks, "detect_leaks"); } void InitializeFlags(Flags *f, const char *env) { CommonFlags *cf = common_flags(); + SetCommonFlagDefaults(); cf->external_symbolizer_path = GetEnv("ASAN_SYMBOLIZER_PATH"); - cf->symbolize = true; cf->malloc_context_size = kDefaultMallocContextSize; - cf->fast_unwind_on_fatal = false; - cf->fast_unwind_on_malloc = true; - cf->strip_path_prefix = ""; internal_memset(f, 0, sizeof(*f)); f->quarantine_size = (ASAN_LOW_MEMORY) ? 1UL << 26 : 1UL << 28; - f->verbosity = 0; f->redzone = 16; f->debug = false; f->report_globals = 1; @@ -147,7 +146,8 @@ void InitializeFlags(Flags *f, const char *env) { f->replace_str = true; f->replace_intrin = true; f->mac_ignore_invalid_free = false; - f->use_fake_stack = true; + f->detect_stack_use_after_return = false; // Also needs the compiler flag. + f->uar_stack_size_log = 0; f->max_malloc_fill_size = 0x1000; // By default, fill only the first 4K. f->malloc_fill_byte = 0xbe; f->exitcode = ASAN_DEFAULT_FAILURE_EXITCODE; @@ -162,25 +162,24 @@ void InitializeFlags(Flags *f, const char *env) { f->print_stats = false; f->print_legend = true; f->atexit = false; + f->coverage = false; f->disable_core = (SANITIZER_WORDSIZE == 64); f->allow_reexec = true; f->print_full_thread_history = true; - f->log_path = 0; f->poison_heap = true; - // Turn off alloc/dealloc mismatch checker on Mac for now. - // TODO(glider): Fix known issues and enable this back. - f->alloc_dealloc_mismatch = (SANITIZER_MAC == 0);; - f->use_stack_depot = true; + f->poison_partial = true; + // Turn off alloc/dealloc mismatch checker on Mac and Windows for now. + // TODO(glider,timurrrr): Fix known issues and enable this back. + f->alloc_dealloc_mismatch = (SANITIZER_MAC == 0) && (SANITIZER_WINDOWS == 0); f->strict_memcmp = true; f->strict_init_order = false; - f->detect_leaks = false; // Override from compile definition. ParseFlagsFromString(f, MaybeUseAsanDefaultOptionsCompileDefiniton()); // Override from user-specified string. ParseFlagsFromString(f, MaybeCallAsanDefaultOptions()); - if (flags()->verbosity) { + if (common_flags()->verbosity) { Report("Using the defaults from __asan_default_options: %s\n", MaybeCallAsanDefaultOptions()); } @@ -189,17 +188,17 @@ void InitializeFlags(Flags *f, const char *env) { ParseFlagsFromString(f, env); #if !CAN_SANITIZE_LEAKS - if (f->detect_leaks) { + if (cf->detect_leaks) { Report("%s: detect_leaks is not supported on this platform.\n", SanitizerToolName); - f->detect_leaks = false; + cf->detect_leaks = false; } #endif - if (f->detect_leaks && !f->use_stack_depot) { - Report("%s: detect_leaks is ignored (requires use_stack_depot).\n", - SanitizerToolName); - f->detect_leaks = false; + // Make "strict_init_order" imply "check_initialization_order". + // TODO(samsonov): Use a single runtime flag for an init-order checker. + if (f->strict_init_order) { + f->check_initialization_order = true; } } @@ -305,8 +304,6 @@ static NOINLINE void force_interface_symbols() { case 25: __asan_poison_memory_region(0, 0); break; case 26: __asan_unpoison_memory_region(0, 0); break; case 27: __asan_set_error_exit_code(0); break; - case 28: __asan_stack_free(0, 0, 0); break; - case 29: __asan_stack_malloc(0, 0); break; case 30: __asan_before_dynamic_init(0); break; case 31: __asan_after_dynamic_init(); break; case 32: __asan_poison_stack_memory(0, 0); break; @@ -328,22 +325,12 @@ static void asan_atexit() { static void InitializeHighMemEnd() { #if !ASAN_FIXED_MAPPING -#if SANITIZER_WORDSIZE == 64 -# if defined(__powerpc64__) - // FIXME: - // On PowerPC64 we have two different address space layouts: 44- and 46-bit. - // We somehow need to figure our which one we are using now and choose - // one of 0x00000fffffffffffUL and 0x00003fffffffffffUL. - // Note that with 'ulimit -s unlimited' the stack is moved away from the top - // of the address space, so simply checking the stack address is not enough. - kHighMemEnd = (1ULL << 44) - 1; // 0x00000fffffffffffUL -# else - kHighMemEnd = (1ULL << 47) - 1; // 0x00007fffffffffffUL; -# endif -#else // SANITIZER_WORDSIZE == 32 - kHighMemEnd = (1ULL << 32) - 1; // 0xffffffff; -#endif // SANITIZER_WORDSIZE + kHighMemEnd = GetMaxVirtualAddress(); + // Increase kHighMemEnd to make sure it's properly + // aligned together with kHighMemBeg: + kHighMemEnd |= SHADOW_GRANULARITY * GetPageSizeCached() - 1; #endif // !ASAN_FIXED_MAPPING + CHECK_EQ((kHighMemBeg % GetPageSizeCached()), 0); } static void ProtectGap(uptr a, uptr size) { @@ -385,6 +372,7 @@ static void PrintAddressSpaceLayout() { } Printf("\n"); Printf("red_zone=%zu\n", (uptr)flags()->redzone); + Printf("quarantine_size=%zuM\n", (uptr)flags()->quarantine_size >> 20); Printf("malloc_context_size=%zu\n", (uptr)common_flags()->malloc_context_size); @@ -405,7 +393,7 @@ using namespace __asan; // NOLINT #if !SANITIZER_SUPPORTS_WEAK_HOOKS extern "C" { -SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE +SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE const char* __asan_default_options() { return ""; } } // extern "C" #endif @@ -438,6 +426,8 @@ void NOINLINE __asan_handle_no_return() { return; } PoisonShadow(bottom, top - bottom, 0); + if (curr_thread->has_fake_stack()) + curr_thread->fake_stack()->HandleNoReturn(); } void NOINLINE __asan_set_death_callback(void (*callback)(void)) { @@ -463,9 +453,11 @@ void __asan_init() { // initialization steps look at flags(). const char *options = GetEnv("ASAN_OPTIONS"); InitializeFlags(flags(), options); - __sanitizer_set_report_path(flags()->log_path); + __sanitizer_set_report_path(common_flags()->log_path); + __asan_option_detect_stack_use_after_return = + flags()->detect_stack_use_after_return; - if (flags()->verbosity && options) { + if (common_flags()->verbosity && options) { Report("Parsed ASAN_OPTIONS: %s\n", options); } @@ -475,21 +467,16 @@ void __asan_init() { // Setup internal allocator callback. SetLowLevelAllocateCallback(OnLowLevelAllocate); - if (flags()->atexit) { - Atexit(asan_atexit); - } - - // interceptors InitializeAsanInterceptors(); ReplaceSystemMalloc(); ReplaceOperatorsNewAndDelete(); uptr shadow_start = kLowShadowBeg; - if (kLowShadowBeg) shadow_start -= GetMmapGranularity(); - uptr shadow_end = kHighShadowEnd; + if (kLowShadowBeg) + shadow_start -= GetMmapGranularity(); bool full_shadow_is_available = - MemoryRangeIsAvailable(shadow_start, shadow_end); + MemoryRangeIsAvailable(shadow_start, kHighShadowEnd); #if SANITIZER_LINUX && defined(__x86_64__) && !ASAN_FIXED_MAPPING if (!full_shadow_is_available) { @@ -498,7 +485,7 @@ void __asan_init() { } #endif - if (flags()->verbosity) + if (common_flags()->verbosity) PrintAddressSpaceLayout(); if (flags()->disable_core) { @@ -515,7 +502,7 @@ void __asan_init() { ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1); } else if (kMidMemBeg && MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) && - MemoryRangeIsAvailable(kMidMemEnd + 1, shadow_end)) { + MemoryRangeIsAvailable(kMidMemEnd + 1, kHighShadowEnd)) { CHECK(kLowShadowBeg != kLowShadowEnd); // mmap the low shadow plus at least one page at the left. ReserveShadowMemoryRange(shadow_start, kLowShadowEnd); @@ -534,12 +521,18 @@ void __asan_init() { Die(); } + AsanTSDInit(PlatformTSDDtor); InstallSignalHandlers(); + + // Allocator should be initialized before starting external symbolizer, as + // fork() on Mac locks the allocator. + InitializeAllocator(); + // Start symbolizer process if necessary. - const char* external_symbolizer = common_flags()->external_symbolizer_path; - if (common_flags()->symbolize && external_symbolizer && - external_symbolizer[0]) { - InitializeExternalSymbolizer(external_symbolizer); + if (common_flags()->symbolize) { + Symbolizer::Init(common_flags()->external_symbolizer_path); + } else { + Symbolizer::Disable(); } // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited @@ -547,8 +540,16 @@ void __asan_init() { asan_inited = 1; asan_init_is_running = false; + if (flags()->atexit) + Atexit(asan_atexit); + + if (flags()->coverage) + Atexit(__sanitizer_cov_dump); + + // interceptors + InitTlsSize(); + // Create main thread. - AsanTSDInit(AsanThread::TSDDtor); AsanThread *main_thread = AsanThread::Create(0, 0); CreateThreadContextArgs create_main_args = { main_thread, 0 }; u32 main_tid = asanThreadRegistry().CreateThread( @@ -558,16 +559,14 @@ void __asan_init() { main_thread->ThreadStart(internal_getpid()); force_interface_symbols(); // no-op. - InitializeAllocator(); - #if CAN_SANITIZE_LEAKS __lsan::InitCommonLsan(); - if (flags()->detect_leaks) { + if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) { Atexit(__lsan::DoLeakCheck); } #endif // CAN_SANITIZE_LEAKS - if (flags()->verbosity) { + if (common_flags()->verbosity) { Report("AddressSanitizer Init done\n"); } } |