| //===-- asan_activation.cpp -------------------------------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file is a part of AddressSanitizer, an address sanity checker. |
| // |
| // ASan activation/deactivation logic. |
| //===----------------------------------------------------------------------===// |
| |
| #include "asan_activation.h" |
| #include "asan_allocator.h" |
| #include "asan_flags.h" |
| #include "asan_internal.h" |
| #include "asan_mapping.h" |
| #include "asan_poisoning.h" |
| #include "asan_stack.h" |
| #include "sanitizer_common/sanitizer_common.h" |
| #include "sanitizer_common/sanitizer_flags.h" |
| |
| namespace __asan { |
| |
| static struct AsanDeactivatedFlags { |
| AllocatorOptions allocator_options; |
| int malloc_context_size; |
| bool poison_heap; |
| bool coverage; |
| const char *coverage_dir; |
| |
| void RegisterActivationFlags(FlagParser *parser, Flags *f, CommonFlags *cf) { |
| #define ASAN_ACTIVATION_FLAG(Type, Name) \ |
| RegisterFlag(parser, #Name, "", &f->Name); |
| #define COMMON_ACTIVATION_FLAG(Type, Name) \ |
| RegisterFlag(parser, #Name, "", &cf->Name); |
| #include "asan_activation_flags.inc" |
| #undef ASAN_ACTIVATION_FLAG |
| #undef COMMON_ACTIVATION_FLAG |
| |
| RegisterIncludeFlags(parser, cf); |
| } |
| |
| void OverrideFromActivationFlags() { |
| Flags f; |
| CommonFlags cf; |
| FlagParser parser; |
| RegisterActivationFlags(&parser, &f, &cf); |
| |
| cf.SetDefaults(); |
| // Copy the current activation flags. |
| allocator_options.CopyTo(&f, &cf); |
| cf.malloc_context_size = malloc_context_size; |
| f.poison_heap = poison_heap; |
| cf.coverage = coverage; |
| cf.coverage_dir = coverage_dir; |
| cf.verbosity = Verbosity(); |
| cf.help = false; // this is activation-specific help |
| |
| // Check if activation flags need to be overriden. |
| if (const char *env = GetEnv("ASAN_ACTIVATION_OPTIONS")) { |
| parser.ParseString(env); |
| } |
| |
| InitializeCommonFlags(&cf); |
| |
| if (Verbosity()) ReportUnrecognizedFlags(); |
| |
| if (cf.help) parser.PrintFlagDescriptions(); |
| |
| allocator_options.SetFrom(&f, &cf); |
| malloc_context_size = cf.malloc_context_size; |
| poison_heap = f.poison_heap; |
| coverage = cf.coverage; |
| coverage_dir = cf.coverage_dir; |
| } |
| |
| void Print() { |
| Report( |
| "quarantine_size_mb %d, thread_local_quarantine_size_kb %d, " |
| "max_redzone %d, poison_heap %d, malloc_context_size %d, " |
| "alloc_dealloc_mismatch %d, allocator_may_return_null %d, coverage %d, " |
| "coverage_dir %s, allocator_release_to_os_interval_ms %d\n", |
| allocator_options.quarantine_size_mb, |
| allocator_options.thread_local_quarantine_size_kb, |
| allocator_options.max_redzone, poison_heap, malloc_context_size, |
| allocator_options.alloc_dealloc_mismatch, |
| allocator_options.may_return_null, coverage, coverage_dir, |
| allocator_options.release_to_os_interval_ms); |
| } |
| } asan_deactivated_flags; |
| |
| static bool asan_is_deactivated; |
| |
| void AsanDeactivate() { |
| CHECK(!asan_is_deactivated); |
| VReport(1, "Deactivating ASan\n"); |
| |
| // Stash runtime state. |
| GetAllocatorOptions(&asan_deactivated_flags.allocator_options); |
| asan_deactivated_flags.malloc_context_size = GetMallocContextSize(); |
| asan_deactivated_flags.poison_heap = CanPoisonMemory(); |
| asan_deactivated_flags.coverage = common_flags()->coverage; |
| asan_deactivated_flags.coverage_dir = common_flags()->coverage_dir; |
| |
| // Deactivate the runtime. |
| SetCanPoisonMemory(false); |
| SetMallocContextSize(1); |
| |
| AllocatorOptions disabled = asan_deactivated_flags.allocator_options; |
| disabled.quarantine_size_mb = 0; |
| disabled.thread_local_quarantine_size_kb = 0; |
| // Redzone must be at least Max(16, granularity) bytes long. |
| disabled.min_redzone = Max(16, (int)SHADOW_GRANULARITY); |
| disabled.max_redzone = disabled.min_redzone; |
| disabled.alloc_dealloc_mismatch = false; |
| disabled.may_return_null = true; |
| ReInitializeAllocator(disabled); |
| |
| asan_is_deactivated = true; |
| } |
| |
| void AsanActivate() { |
| if (!asan_is_deactivated) return; |
| VReport(1, "Activating ASan\n"); |
| |
| UpdateProcessName(); |
| |
| asan_deactivated_flags.OverrideFromActivationFlags(); |
| |
| SetCanPoisonMemory(asan_deactivated_flags.poison_heap); |
| SetMallocContextSize(asan_deactivated_flags.malloc_context_size); |
| ReInitializeAllocator(asan_deactivated_flags.allocator_options); |
| |
| asan_is_deactivated = false; |
| if (Verbosity()) { |
| Report("Activated with flags:\n"); |
| asan_deactivated_flags.Print(); |
| } |
| } |
| |
| } // namespace __asan |