asan_activation.cpp 4.6 KB

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