xref: /freebsd/contrib/llvm-project/compiler-rt/lib/asan/asan_activation.cpp (revision 0eae32dcef82f6f06de6419a0d623d7def0cc8f6)
168d75effSDimitry Andric //===-- asan_activation.cpp -------------------------------------*- C++ -*-===//
268d75effSDimitry Andric //
368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
668d75effSDimitry Andric //
768d75effSDimitry Andric //===----------------------------------------------------------------------===//
868d75effSDimitry Andric //
968d75effSDimitry Andric // This file is a part of AddressSanitizer, an address sanity checker.
1068d75effSDimitry Andric //
1168d75effSDimitry Andric // ASan activation/deactivation logic.
1268d75effSDimitry Andric //===----------------------------------------------------------------------===//
1368d75effSDimitry Andric 
1468d75effSDimitry Andric #include "asan_activation.h"
1568d75effSDimitry Andric #include "asan_allocator.h"
1668d75effSDimitry Andric #include "asan_flags.h"
1768d75effSDimitry Andric #include "asan_internal.h"
1868d75effSDimitry Andric #include "asan_mapping.h"
1968d75effSDimitry Andric #include "asan_poisoning.h"
2068d75effSDimitry Andric #include "asan_stack.h"
2168d75effSDimitry Andric #include "sanitizer_common/sanitizer_common.h"
2268d75effSDimitry Andric #include "sanitizer_common/sanitizer_flags.h"
2368d75effSDimitry Andric 
2468d75effSDimitry Andric namespace __asan {
2568d75effSDimitry Andric 
2668d75effSDimitry Andric static struct AsanDeactivatedFlags {
2768d75effSDimitry Andric   AllocatorOptions allocator_options;
2868d75effSDimitry Andric   int malloc_context_size;
2968d75effSDimitry Andric   bool poison_heap;
3068d75effSDimitry Andric   bool coverage;
3168d75effSDimitry Andric   const char *coverage_dir;
3268d75effSDimitry Andric 
RegisterActivationFlags__asan::AsanDeactivatedFlags3368d75effSDimitry Andric   void RegisterActivationFlags(FlagParser *parser, Flags *f, CommonFlags *cf) {
3468d75effSDimitry Andric #define ASAN_ACTIVATION_FLAG(Type, Name) \
3568d75effSDimitry Andric   RegisterFlag(parser, #Name, "", &f->Name);
3668d75effSDimitry Andric #define COMMON_ACTIVATION_FLAG(Type, Name) \
3768d75effSDimitry Andric   RegisterFlag(parser, #Name, "", &cf->Name);
3868d75effSDimitry Andric #include "asan_activation_flags.inc"
3968d75effSDimitry Andric #undef ASAN_ACTIVATION_FLAG
4068d75effSDimitry Andric #undef COMMON_ACTIVATION_FLAG
4168d75effSDimitry Andric 
4268d75effSDimitry Andric     RegisterIncludeFlags(parser, cf);
4368d75effSDimitry Andric   }
4468d75effSDimitry Andric 
OverrideFromActivationFlags__asan::AsanDeactivatedFlags4568d75effSDimitry Andric   void OverrideFromActivationFlags() {
4668d75effSDimitry Andric     Flags f;
4768d75effSDimitry Andric     CommonFlags cf;
4868d75effSDimitry Andric     FlagParser parser;
4968d75effSDimitry Andric     RegisterActivationFlags(&parser, &f, &cf);
5068d75effSDimitry Andric 
5168d75effSDimitry Andric     cf.SetDefaults();
5268d75effSDimitry Andric     // Copy the current activation flags.
5368d75effSDimitry Andric     allocator_options.CopyTo(&f, &cf);
5468d75effSDimitry Andric     cf.malloc_context_size = malloc_context_size;
5568d75effSDimitry Andric     f.poison_heap = poison_heap;
5668d75effSDimitry Andric     cf.coverage = coverage;
5768d75effSDimitry Andric     cf.coverage_dir = coverage_dir;
5868d75effSDimitry Andric     cf.verbosity = Verbosity();
5968d75effSDimitry Andric     cf.help = false; // this is activation-specific help
6068d75effSDimitry Andric 
6168d75effSDimitry Andric     // Check if activation flags need to be overriden.
6268d75effSDimitry Andric     if (const char *env = GetEnv("ASAN_ACTIVATION_OPTIONS")) {
6368d75effSDimitry Andric       parser.ParseString(env);
6468d75effSDimitry Andric     }
6568d75effSDimitry Andric 
6668d75effSDimitry Andric     InitializeCommonFlags(&cf);
6768d75effSDimitry Andric 
6868d75effSDimitry Andric     if (Verbosity()) ReportUnrecognizedFlags();
6968d75effSDimitry Andric 
7068d75effSDimitry Andric     if (cf.help) parser.PrintFlagDescriptions();
7168d75effSDimitry Andric 
7268d75effSDimitry Andric     allocator_options.SetFrom(&f, &cf);
7368d75effSDimitry Andric     malloc_context_size = cf.malloc_context_size;
7468d75effSDimitry Andric     poison_heap = f.poison_heap;
7568d75effSDimitry Andric     coverage = cf.coverage;
7668d75effSDimitry Andric     coverage_dir = cf.coverage_dir;
7768d75effSDimitry Andric   }
7868d75effSDimitry Andric 
Print__asan::AsanDeactivatedFlags7968d75effSDimitry Andric   void Print() {
8068d75effSDimitry Andric     Report(
8168d75effSDimitry Andric         "quarantine_size_mb %d, thread_local_quarantine_size_kb %d, "
8268d75effSDimitry Andric         "max_redzone %d, poison_heap %d, malloc_context_size %d, "
8368d75effSDimitry Andric         "alloc_dealloc_mismatch %d, allocator_may_return_null %d, coverage %d, "
8468d75effSDimitry Andric         "coverage_dir %s, allocator_release_to_os_interval_ms %d\n",
8568d75effSDimitry Andric         allocator_options.quarantine_size_mb,
8668d75effSDimitry Andric         allocator_options.thread_local_quarantine_size_kb,
8768d75effSDimitry Andric         allocator_options.max_redzone, poison_heap, malloc_context_size,
8868d75effSDimitry Andric         allocator_options.alloc_dealloc_mismatch,
8968d75effSDimitry Andric         allocator_options.may_return_null, coverage, coverage_dir,
9068d75effSDimitry Andric         allocator_options.release_to_os_interval_ms);
9168d75effSDimitry Andric   }
9268d75effSDimitry Andric } asan_deactivated_flags;
9368d75effSDimitry Andric 
9468d75effSDimitry Andric static bool asan_is_deactivated;
9568d75effSDimitry Andric 
AsanDeactivate()9668d75effSDimitry Andric void AsanDeactivate() {
9768d75effSDimitry Andric   CHECK(!asan_is_deactivated);
9868d75effSDimitry Andric   VReport(1, "Deactivating ASan\n");
9968d75effSDimitry Andric 
10068d75effSDimitry Andric   // Stash runtime state.
10168d75effSDimitry Andric   GetAllocatorOptions(&asan_deactivated_flags.allocator_options);
10268d75effSDimitry Andric   asan_deactivated_flags.malloc_context_size = GetMallocContextSize();
10368d75effSDimitry Andric   asan_deactivated_flags.poison_heap = CanPoisonMemory();
10468d75effSDimitry Andric   asan_deactivated_flags.coverage = common_flags()->coverage;
10568d75effSDimitry Andric   asan_deactivated_flags.coverage_dir = common_flags()->coverage_dir;
10668d75effSDimitry Andric 
10768d75effSDimitry Andric   // Deactivate the runtime.
10868d75effSDimitry Andric   SetCanPoisonMemory(false);
10968d75effSDimitry Andric   SetMallocContextSize(1);
11068d75effSDimitry Andric 
11168d75effSDimitry Andric   AllocatorOptions disabled = asan_deactivated_flags.allocator_options;
11268d75effSDimitry Andric   disabled.quarantine_size_mb = 0;
11368d75effSDimitry Andric   disabled.thread_local_quarantine_size_kb = 0;
11468d75effSDimitry Andric   // Redzone must be at least Max(16, granularity) bytes long.
115*0eae32dcSDimitry Andric   disabled.min_redzone = Max(16, (int)ASAN_SHADOW_GRANULARITY);
11668d75effSDimitry Andric   disabled.max_redzone = disabled.min_redzone;
11768d75effSDimitry Andric   disabled.alloc_dealloc_mismatch = false;
11868d75effSDimitry Andric   disabled.may_return_null = true;
11968d75effSDimitry Andric   ReInitializeAllocator(disabled);
12068d75effSDimitry Andric 
12168d75effSDimitry Andric   asan_is_deactivated = true;
12268d75effSDimitry Andric }
12368d75effSDimitry Andric 
AsanActivate()12468d75effSDimitry Andric void AsanActivate() {
12568d75effSDimitry Andric   if (!asan_is_deactivated) return;
12668d75effSDimitry Andric   VReport(1, "Activating ASan\n");
12768d75effSDimitry Andric 
12868d75effSDimitry Andric   UpdateProcessName();
12968d75effSDimitry Andric 
13068d75effSDimitry Andric   asan_deactivated_flags.OverrideFromActivationFlags();
13168d75effSDimitry Andric 
13268d75effSDimitry Andric   SetCanPoisonMemory(asan_deactivated_flags.poison_heap);
13368d75effSDimitry Andric   SetMallocContextSize(asan_deactivated_flags.malloc_context_size);
13468d75effSDimitry Andric   ReInitializeAllocator(asan_deactivated_flags.allocator_options);
13568d75effSDimitry Andric 
13668d75effSDimitry Andric   asan_is_deactivated = false;
13768d75effSDimitry Andric   if (Verbosity()) {
13868d75effSDimitry Andric     Report("Activated with flags:\n");
13968d75effSDimitry Andric     asan_deactivated_flags.Print();
14068d75effSDimitry Andric   }
14168d75effSDimitry Andric }
14268d75effSDimitry Andric 
14368d75effSDimitry Andric }  // namespace __asan
144