xref: /openbsd-src/gnu/llvm/compiler-rt/lib/asan/asan_activation.cpp (revision 810390e339a5425391477d5d41c78d7cab2424ac)
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