13cab2bb3Spatrick //===-- asan_activation.cpp -------------------------------------*- C++ -*-===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick //
93cab2bb3Spatrick // This file is a part of AddressSanitizer, an address sanity checker.
103cab2bb3Spatrick //
113cab2bb3Spatrick // ASan activation/deactivation logic.
123cab2bb3Spatrick //===----------------------------------------------------------------------===//
133cab2bb3Spatrick
143cab2bb3Spatrick #include "asan_activation.h"
153cab2bb3Spatrick #include "asan_allocator.h"
163cab2bb3Spatrick #include "asan_flags.h"
173cab2bb3Spatrick #include "asan_internal.h"
183cab2bb3Spatrick #include "asan_mapping.h"
193cab2bb3Spatrick #include "asan_poisoning.h"
203cab2bb3Spatrick #include "asan_stack.h"
213cab2bb3Spatrick #include "sanitizer_common/sanitizer_common.h"
223cab2bb3Spatrick #include "sanitizer_common/sanitizer_flags.h"
233cab2bb3Spatrick
243cab2bb3Spatrick namespace __asan {
253cab2bb3Spatrick
263cab2bb3Spatrick static struct AsanDeactivatedFlags {
273cab2bb3Spatrick AllocatorOptions allocator_options;
283cab2bb3Spatrick int malloc_context_size;
293cab2bb3Spatrick bool poison_heap;
303cab2bb3Spatrick bool coverage;
313cab2bb3Spatrick const char *coverage_dir;
323cab2bb3Spatrick
RegisterActivationFlags__asan::AsanDeactivatedFlags333cab2bb3Spatrick void RegisterActivationFlags(FlagParser *parser, Flags *f, CommonFlags *cf) {
343cab2bb3Spatrick #define ASAN_ACTIVATION_FLAG(Type, Name) \
353cab2bb3Spatrick RegisterFlag(parser, #Name, "", &f->Name);
363cab2bb3Spatrick #define COMMON_ACTIVATION_FLAG(Type, Name) \
373cab2bb3Spatrick RegisterFlag(parser, #Name, "", &cf->Name);
383cab2bb3Spatrick #include "asan_activation_flags.inc"
393cab2bb3Spatrick #undef ASAN_ACTIVATION_FLAG
403cab2bb3Spatrick #undef COMMON_ACTIVATION_FLAG
413cab2bb3Spatrick
423cab2bb3Spatrick RegisterIncludeFlags(parser, cf);
433cab2bb3Spatrick }
443cab2bb3Spatrick
OverrideFromActivationFlags__asan::AsanDeactivatedFlags453cab2bb3Spatrick void OverrideFromActivationFlags() {
463cab2bb3Spatrick Flags f;
473cab2bb3Spatrick CommonFlags cf;
483cab2bb3Spatrick FlagParser parser;
493cab2bb3Spatrick RegisterActivationFlags(&parser, &f, &cf);
503cab2bb3Spatrick
513cab2bb3Spatrick cf.SetDefaults();
523cab2bb3Spatrick // Copy the current activation flags.
533cab2bb3Spatrick allocator_options.CopyTo(&f, &cf);
543cab2bb3Spatrick cf.malloc_context_size = malloc_context_size;
553cab2bb3Spatrick f.poison_heap = poison_heap;
563cab2bb3Spatrick cf.coverage = coverage;
573cab2bb3Spatrick cf.coverage_dir = coverage_dir;
583cab2bb3Spatrick cf.verbosity = Verbosity();
593cab2bb3Spatrick cf.help = false; // this is activation-specific help
603cab2bb3Spatrick
613cab2bb3Spatrick // Check if activation flags need to be overriden.
623cab2bb3Spatrick if (const char *env = GetEnv("ASAN_ACTIVATION_OPTIONS")) {
633cab2bb3Spatrick parser.ParseString(env);
643cab2bb3Spatrick }
653cab2bb3Spatrick
663cab2bb3Spatrick InitializeCommonFlags(&cf);
673cab2bb3Spatrick
683cab2bb3Spatrick if (Verbosity()) ReportUnrecognizedFlags();
693cab2bb3Spatrick
703cab2bb3Spatrick if (cf.help) parser.PrintFlagDescriptions();
713cab2bb3Spatrick
723cab2bb3Spatrick allocator_options.SetFrom(&f, &cf);
733cab2bb3Spatrick malloc_context_size = cf.malloc_context_size;
743cab2bb3Spatrick poison_heap = f.poison_heap;
753cab2bb3Spatrick coverage = cf.coverage;
763cab2bb3Spatrick coverage_dir = cf.coverage_dir;
773cab2bb3Spatrick }
783cab2bb3Spatrick
Print__asan::AsanDeactivatedFlags793cab2bb3Spatrick void Print() {
803cab2bb3Spatrick Report(
813cab2bb3Spatrick "quarantine_size_mb %d, thread_local_quarantine_size_kb %d, "
823cab2bb3Spatrick "max_redzone %d, poison_heap %d, malloc_context_size %d, "
833cab2bb3Spatrick "alloc_dealloc_mismatch %d, allocator_may_return_null %d, coverage %d, "
843cab2bb3Spatrick "coverage_dir %s, allocator_release_to_os_interval_ms %d\n",
853cab2bb3Spatrick allocator_options.quarantine_size_mb,
863cab2bb3Spatrick allocator_options.thread_local_quarantine_size_kb,
873cab2bb3Spatrick allocator_options.max_redzone, poison_heap, malloc_context_size,
883cab2bb3Spatrick allocator_options.alloc_dealloc_mismatch,
893cab2bb3Spatrick allocator_options.may_return_null, coverage, coverage_dir,
903cab2bb3Spatrick allocator_options.release_to_os_interval_ms);
913cab2bb3Spatrick }
923cab2bb3Spatrick } asan_deactivated_flags;
933cab2bb3Spatrick
943cab2bb3Spatrick static bool asan_is_deactivated;
953cab2bb3Spatrick
AsanDeactivate()963cab2bb3Spatrick void AsanDeactivate() {
973cab2bb3Spatrick CHECK(!asan_is_deactivated);
983cab2bb3Spatrick VReport(1, "Deactivating ASan\n");
993cab2bb3Spatrick
1003cab2bb3Spatrick // Stash runtime state.
1013cab2bb3Spatrick GetAllocatorOptions(&asan_deactivated_flags.allocator_options);
1023cab2bb3Spatrick asan_deactivated_flags.malloc_context_size = GetMallocContextSize();
1033cab2bb3Spatrick asan_deactivated_flags.poison_heap = CanPoisonMemory();
1043cab2bb3Spatrick asan_deactivated_flags.coverage = common_flags()->coverage;
1053cab2bb3Spatrick asan_deactivated_flags.coverage_dir = common_flags()->coverage_dir;
1063cab2bb3Spatrick
1073cab2bb3Spatrick // Deactivate the runtime.
1083cab2bb3Spatrick SetCanPoisonMemory(false);
1093cab2bb3Spatrick SetMallocContextSize(1);
1103cab2bb3Spatrick
1113cab2bb3Spatrick AllocatorOptions disabled = asan_deactivated_flags.allocator_options;
1123cab2bb3Spatrick disabled.quarantine_size_mb = 0;
1133cab2bb3Spatrick disabled.thread_local_quarantine_size_kb = 0;
1143cab2bb3Spatrick // Redzone must be at least Max(16, granularity) bytes long.
115*810390e3Srobert disabled.min_redzone = Max(16, (int)ASAN_SHADOW_GRANULARITY);
1163cab2bb3Spatrick disabled.max_redzone = disabled.min_redzone;
1173cab2bb3Spatrick disabled.alloc_dealloc_mismatch = false;
1183cab2bb3Spatrick disabled.may_return_null = true;
1193cab2bb3Spatrick ReInitializeAllocator(disabled);
1203cab2bb3Spatrick
1213cab2bb3Spatrick asan_is_deactivated = true;
1223cab2bb3Spatrick }
1233cab2bb3Spatrick
AsanActivate()1243cab2bb3Spatrick void AsanActivate() {
1253cab2bb3Spatrick if (!asan_is_deactivated) return;
1263cab2bb3Spatrick VReport(1, "Activating ASan\n");
1273cab2bb3Spatrick
1283cab2bb3Spatrick UpdateProcessName();
1293cab2bb3Spatrick
1303cab2bb3Spatrick asan_deactivated_flags.OverrideFromActivationFlags();
1313cab2bb3Spatrick
1323cab2bb3Spatrick SetCanPoisonMemory(asan_deactivated_flags.poison_heap);
1333cab2bb3Spatrick SetMallocContextSize(asan_deactivated_flags.malloc_context_size);
1343cab2bb3Spatrick ReInitializeAllocator(asan_deactivated_flags.allocator_options);
1353cab2bb3Spatrick
1363cab2bb3Spatrick asan_is_deactivated = false;
1373cab2bb3Spatrick if (Verbosity()) {
1383cab2bb3Spatrick Report("Activated with flags:\n");
1393cab2bb3Spatrick asan_deactivated_flags.Print();
1403cab2bb3Spatrick }
1413cab2bb3Spatrick }
1423cab2bb3Spatrick
1433cab2bb3Spatrick } // namespace __asan
144