xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/asan/asan_activation.cpp (revision 68d75eff68281c1b445e3010bb975eae07aac225)
1*68d75effSDimitry Andric //===-- asan_activation.cpp -------------------------------------*- C++ -*-===//
2*68d75effSDimitry Andric //
3*68d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*68d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*68d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*68d75effSDimitry Andric //
7*68d75effSDimitry Andric //===----------------------------------------------------------------------===//
8*68d75effSDimitry Andric //
9*68d75effSDimitry Andric // This file is a part of AddressSanitizer, an address sanity checker.
10*68d75effSDimitry Andric //
11*68d75effSDimitry Andric // ASan activation/deactivation logic.
12*68d75effSDimitry Andric //===----------------------------------------------------------------------===//
13*68d75effSDimitry Andric 
14*68d75effSDimitry Andric #include "asan_activation.h"
15*68d75effSDimitry Andric #include "asan_allocator.h"
16*68d75effSDimitry Andric #include "asan_flags.h"
17*68d75effSDimitry Andric #include "asan_internal.h"
18*68d75effSDimitry Andric #include "asan_mapping.h"
19*68d75effSDimitry Andric #include "asan_poisoning.h"
20*68d75effSDimitry Andric #include "asan_stack.h"
21*68d75effSDimitry Andric #include "sanitizer_common/sanitizer_common.h"
22*68d75effSDimitry Andric #include "sanitizer_common/sanitizer_flags.h"
23*68d75effSDimitry Andric 
24*68d75effSDimitry Andric namespace __asan {
25*68d75effSDimitry Andric 
26*68d75effSDimitry Andric static struct AsanDeactivatedFlags {
27*68d75effSDimitry Andric   AllocatorOptions allocator_options;
28*68d75effSDimitry Andric   int malloc_context_size;
29*68d75effSDimitry Andric   bool poison_heap;
30*68d75effSDimitry Andric   bool coverage;
31*68d75effSDimitry Andric   const char *coverage_dir;
32*68d75effSDimitry Andric 
33*68d75effSDimitry Andric   void RegisterActivationFlags(FlagParser *parser, Flags *f, CommonFlags *cf) {
34*68d75effSDimitry Andric #define ASAN_ACTIVATION_FLAG(Type, Name) \
35*68d75effSDimitry Andric   RegisterFlag(parser, #Name, "", &f->Name);
36*68d75effSDimitry Andric #define COMMON_ACTIVATION_FLAG(Type, Name) \
37*68d75effSDimitry Andric   RegisterFlag(parser, #Name, "", &cf->Name);
38*68d75effSDimitry Andric #include "asan_activation_flags.inc"
39*68d75effSDimitry Andric #undef ASAN_ACTIVATION_FLAG
40*68d75effSDimitry Andric #undef COMMON_ACTIVATION_FLAG
41*68d75effSDimitry Andric 
42*68d75effSDimitry Andric     RegisterIncludeFlags(parser, cf);
43*68d75effSDimitry Andric   }
44*68d75effSDimitry Andric 
45*68d75effSDimitry Andric   void OverrideFromActivationFlags() {
46*68d75effSDimitry Andric     Flags f;
47*68d75effSDimitry Andric     CommonFlags cf;
48*68d75effSDimitry Andric     FlagParser parser;
49*68d75effSDimitry Andric     RegisterActivationFlags(&parser, &f, &cf);
50*68d75effSDimitry Andric 
51*68d75effSDimitry Andric     cf.SetDefaults();
52*68d75effSDimitry Andric     // Copy the current activation flags.
53*68d75effSDimitry Andric     allocator_options.CopyTo(&f, &cf);
54*68d75effSDimitry Andric     cf.malloc_context_size = malloc_context_size;
55*68d75effSDimitry Andric     f.poison_heap = poison_heap;
56*68d75effSDimitry Andric     cf.coverage = coverage;
57*68d75effSDimitry Andric     cf.coverage_dir = coverage_dir;
58*68d75effSDimitry Andric     cf.verbosity = Verbosity();
59*68d75effSDimitry Andric     cf.help = false; // this is activation-specific help
60*68d75effSDimitry Andric 
61*68d75effSDimitry Andric     // Check if activation flags need to be overriden.
62*68d75effSDimitry Andric     if (const char *env = GetEnv("ASAN_ACTIVATION_OPTIONS")) {
63*68d75effSDimitry Andric       parser.ParseString(env);
64*68d75effSDimitry Andric     }
65*68d75effSDimitry Andric 
66*68d75effSDimitry Andric     InitializeCommonFlags(&cf);
67*68d75effSDimitry Andric 
68*68d75effSDimitry Andric     if (Verbosity()) ReportUnrecognizedFlags();
69*68d75effSDimitry Andric 
70*68d75effSDimitry Andric     if (cf.help) parser.PrintFlagDescriptions();
71*68d75effSDimitry Andric 
72*68d75effSDimitry Andric     allocator_options.SetFrom(&f, &cf);
73*68d75effSDimitry Andric     malloc_context_size = cf.malloc_context_size;
74*68d75effSDimitry Andric     poison_heap = f.poison_heap;
75*68d75effSDimitry Andric     coverage = cf.coverage;
76*68d75effSDimitry Andric     coverage_dir = cf.coverage_dir;
77*68d75effSDimitry Andric   }
78*68d75effSDimitry Andric 
79*68d75effSDimitry Andric   void Print() {
80*68d75effSDimitry Andric     Report(
81*68d75effSDimitry Andric         "quarantine_size_mb %d, thread_local_quarantine_size_kb %d, "
82*68d75effSDimitry Andric         "max_redzone %d, poison_heap %d, malloc_context_size %d, "
83*68d75effSDimitry Andric         "alloc_dealloc_mismatch %d, allocator_may_return_null %d, coverage %d, "
84*68d75effSDimitry Andric         "coverage_dir %s, allocator_release_to_os_interval_ms %d\n",
85*68d75effSDimitry Andric         allocator_options.quarantine_size_mb,
86*68d75effSDimitry Andric         allocator_options.thread_local_quarantine_size_kb,
87*68d75effSDimitry Andric         allocator_options.max_redzone, poison_heap, malloc_context_size,
88*68d75effSDimitry Andric         allocator_options.alloc_dealloc_mismatch,
89*68d75effSDimitry Andric         allocator_options.may_return_null, coverage, coverage_dir,
90*68d75effSDimitry Andric         allocator_options.release_to_os_interval_ms);
91*68d75effSDimitry Andric   }
92*68d75effSDimitry Andric } asan_deactivated_flags;
93*68d75effSDimitry Andric 
94*68d75effSDimitry Andric static bool asan_is_deactivated;
95*68d75effSDimitry Andric 
96*68d75effSDimitry Andric void AsanDeactivate() {
97*68d75effSDimitry Andric   CHECK(!asan_is_deactivated);
98*68d75effSDimitry Andric   VReport(1, "Deactivating ASan\n");
99*68d75effSDimitry Andric 
100*68d75effSDimitry Andric   // Stash runtime state.
101*68d75effSDimitry Andric   GetAllocatorOptions(&asan_deactivated_flags.allocator_options);
102*68d75effSDimitry Andric   asan_deactivated_flags.malloc_context_size = GetMallocContextSize();
103*68d75effSDimitry Andric   asan_deactivated_flags.poison_heap = CanPoisonMemory();
104*68d75effSDimitry Andric   asan_deactivated_flags.coverage = common_flags()->coverage;
105*68d75effSDimitry Andric   asan_deactivated_flags.coverage_dir = common_flags()->coverage_dir;
106*68d75effSDimitry Andric 
107*68d75effSDimitry Andric   // Deactivate the runtime.
108*68d75effSDimitry Andric   SetCanPoisonMemory(false);
109*68d75effSDimitry Andric   SetMallocContextSize(1);
110*68d75effSDimitry Andric 
111*68d75effSDimitry Andric   AllocatorOptions disabled = asan_deactivated_flags.allocator_options;
112*68d75effSDimitry Andric   disabled.quarantine_size_mb = 0;
113*68d75effSDimitry Andric   disabled.thread_local_quarantine_size_kb = 0;
114*68d75effSDimitry Andric   // Redzone must be at least Max(16, granularity) bytes long.
115*68d75effSDimitry Andric   disabled.min_redzone = Max(16, (int)SHADOW_GRANULARITY);
116*68d75effSDimitry Andric   disabled.max_redzone = disabled.min_redzone;
117*68d75effSDimitry Andric   disabled.alloc_dealloc_mismatch = false;
118*68d75effSDimitry Andric   disabled.may_return_null = true;
119*68d75effSDimitry Andric   ReInitializeAllocator(disabled);
120*68d75effSDimitry Andric 
121*68d75effSDimitry Andric   asan_is_deactivated = true;
122*68d75effSDimitry Andric }
123*68d75effSDimitry Andric 
124*68d75effSDimitry Andric void AsanActivate() {
125*68d75effSDimitry Andric   if (!asan_is_deactivated) return;
126*68d75effSDimitry Andric   VReport(1, "Activating ASan\n");
127*68d75effSDimitry Andric 
128*68d75effSDimitry Andric   UpdateProcessName();
129*68d75effSDimitry Andric 
130*68d75effSDimitry Andric   asan_deactivated_flags.OverrideFromActivationFlags();
131*68d75effSDimitry Andric 
132*68d75effSDimitry Andric   SetCanPoisonMemory(asan_deactivated_flags.poison_heap);
133*68d75effSDimitry Andric   SetMallocContextSize(asan_deactivated_flags.malloc_context_size);
134*68d75effSDimitry Andric   ReInitializeAllocator(asan_deactivated_flags.allocator_options);
135*68d75effSDimitry Andric 
136*68d75effSDimitry Andric   asan_is_deactivated = false;
137*68d75effSDimitry Andric   if (Verbosity()) {
138*68d75effSDimitry Andric     Report("Activated with flags:\n");
139*68d75effSDimitry Andric     asan_deactivated_flags.Print();
140*68d75effSDimitry Andric   }
141*68d75effSDimitry Andric }
142*68d75effSDimitry Andric 
143*68d75effSDimitry Andric }  // namespace __asan
144