1353944Sdim//===-- asan_activation.cpp -------------------------------------*- C++ -*-===//
2353944Sdim//
3353944Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353944Sdim// See https://llvm.org/LICENSE.txt for license information.
5353944Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6353944Sdim//
7353944Sdim//===----------------------------------------------------------------------===//
8353944Sdim//
9353944Sdim// This file is a part of AddressSanitizer, an address sanity checker.
10353944Sdim//
11353944Sdim// ASan activation/deactivation logic.
12353944Sdim//===----------------------------------------------------------------------===//
13353944Sdim
14353944Sdim#include "asan_activation.h"
15353944Sdim#include "asan_allocator.h"
16353944Sdim#include "asan_flags.h"
17353944Sdim#include "asan_internal.h"
18353944Sdim#include "asan_mapping.h"
19353944Sdim#include "asan_poisoning.h"
20353944Sdim#include "asan_stack.h"
21353944Sdim#include "sanitizer_common/sanitizer_common.h"
22353944Sdim#include "sanitizer_common/sanitizer_flags.h"
23353944Sdim
24353944Sdimnamespace __asan {
25353944Sdim
26353944Sdimstatic struct AsanDeactivatedFlags {
27353944Sdim  AllocatorOptions allocator_options;
28353944Sdim  int malloc_context_size;
29353944Sdim  bool poison_heap;
30353944Sdim  bool coverage;
31353944Sdim  const char *coverage_dir;
32353944Sdim
33353944Sdim  void RegisterActivationFlags(FlagParser *parser, Flags *f, CommonFlags *cf) {
34353944Sdim#define ASAN_ACTIVATION_FLAG(Type, Name) \
35353944Sdim  RegisterFlag(parser, #Name, "", &f->Name);
36353944Sdim#define COMMON_ACTIVATION_FLAG(Type, Name) \
37353944Sdim  RegisterFlag(parser, #Name, "", &cf->Name);
38353944Sdim#include "asan_activation_flags.inc"
39353944Sdim#undef ASAN_ACTIVATION_FLAG
40353944Sdim#undef COMMON_ACTIVATION_FLAG
41353944Sdim
42353944Sdim    RegisterIncludeFlags(parser, cf);
43353944Sdim  }
44353944Sdim
45353944Sdim  void OverrideFromActivationFlags() {
46353944Sdim    Flags f;
47353944Sdim    CommonFlags cf;
48353944Sdim    FlagParser parser;
49353944Sdim    RegisterActivationFlags(&parser, &f, &cf);
50353944Sdim
51353944Sdim    cf.SetDefaults();
52353944Sdim    // Copy the current activation flags.
53353944Sdim    allocator_options.CopyTo(&f, &cf);
54353944Sdim    cf.malloc_context_size = malloc_context_size;
55353944Sdim    f.poison_heap = poison_heap;
56353944Sdim    cf.coverage = coverage;
57353944Sdim    cf.coverage_dir = coverage_dir;
58353944Sdim    cf.verbosity = Verbosity();
59353944Sdim    cf.help = false; // this is activation-specific help
60353944Sdim
61353944Sdim    // Check if activation flags need to be overriden.
62353944Sdim    if (const char *env = GetEnv("ASAN_ACTIVATION_OPTIONS")) {
63353944Sdim      parser.ParseString(env);
64353944Sdim    }
65353944Sdim
66353944Sdim    InitializeCommonFlags(&cf);
67353944Sdim
68353944Sdim    if (Verbosity()) ReportUnrecognizedFlags();
69353944Sdim
70353944Sdim    if (cf.help) parser.PrintFlagDescriptions();
71353944Sdim
72353944Sdim    allocator_options.SetFrom(&f, &cf);
73353944Sdim    malloc_context_size = cf.malloc_context_size;
74353944Sdim    poison_heap = f.poison_heap;
75353944Sdim    coverage = cf.coverage;
76353944Sdim    coverage_dir = cf.coverage_dir;
77353944Sdim  }
78353944Sdim
79353944Sdim  void Print() {
80353944Sdim    Report(
81353944Sdim        "quarantine_size_mb %d, thread_local_quarantine_size_kb %d, "
82353944Sdim        "max_redzone %d, poison_heap %d, malloc_context_size %d, "
83353944Sdim        "alloc_dealloc_mismatch %d, allocator_may_return_null %d, coverage %d, "
84353944Sdim        "coverage_dir %s, allocator_release_to_os_interval_ms %d\n",
85353944Sdim        allocator_options.quarantine_size_mb,
86353944Sdim        allocator_options.thread_local_quarantine_size_kb,
87353944Sdim        allocator_options.max_redzone, poison_heap, malloc_context_size,
88353944Sdim        allocator_options.alloc_dealloc_mismatch,
89353944Sdim        allocator_options.may_return_null, coverage, coverage_dir,
90353944Sdim        allocator_options.release_to_os_interval_ms);
91353944Sdim  }
92353944Sdim} asan_deactivated_flags;
93353944Sdim
94353944Sdimstatic bool asan_is_deactivated;
95353944Sdim
96353944Sdimvoid AsanDeactivate() {
97353944Sdim  CHECK(!asan_is_deactivated);
98353944Sdim  VReport(1, "Deactivating ASan\n");
99353944Sdim
100353944Sdim  // Stash runtime state.
101353944Sdim  GetAllocatorOptions(&asan_deactivated_flags.allocator_options);
102353944Sdim  asan_deactivated_flags.malloc_context_size = GetMallocContextSize();
103353944Sdim  asan_deactivated_flags.poison_heap = CanPoisonMemory();
104353944Sdim  asan_deactivated_flags.coverage = common_flags()->coverage;
105353944Sdim  asan_deactivated_flags.coverage_dir = common_flags()->coverage_dir;
106353944Sdim
107353944Sdim  // Deactivate the runtime.
108353944Sdim  SetCanPoisonMemory(false);
109353944Sdim  SetMallocContextSize(1);
110353944Sdim
111353944Sdim  AllocatorOptions disabled = asan_deactivated_flags.allocator_options;
112353944Sdim  disabled.quarantine_size_mb = 0;
113353944Sdim  disabled.thread_local_quarantine_size_kb = 0;
114353944Sdim  // Redzone must be at least Max(16, granularity) bytes long.
115353944Sdim  disabled.min_redzone = Max(16, (int)SHADOW_GRANULARITY);
116353944Sdim  disabled.max_redzone = disabled.min_redzone;
117353944Sdim  disabled.alloc_dealloc_mismatch = false;
118353944Sdim  disabled.may_return_null = true;
119353944Sdim  ReInitializeAllocator(disabled);
120353944Sdim
121353944Sdim  asan_is_deactivated = true;
122353944Sdim}
123353944Sdim
124353944Sdimvoid AsanActivate() {
125353944Sdim  if (!asan_is_deactivated) return;
126353944Sdim  VReport(1, "Activating ASan\n");
127353944Sdim
128353944Sdim  UpdateProcessName();
129353944Sdim
130353944Sdim  asan_deactivated_flags.OverrideFromActivationFlags();
131353944Sdim
132353944Sdim  SetCanPoisonMemory(asan_deactivated_flags.poison_heap);
133353944Sdim  SetMallocContextSize(asan_deactivated_flags.malloc_context_size);
134353944Sdim  ReInitializeAllocator(asan_deactivated_flags.allocator_options);
135353944Sdim
136353944Sdim  asan_is_deactivated = false;
137353944Sdim  if (Verbosity()) {
138353944Sdim    Report("Activated with flags:\n");
139353944Sdim    asan_deactivated_flags.Print();
140353944Sdim  }
141353944Sdim}
142353944Sdim
143353944Sdim}  // namespace __asan
144