asan_poisoning.h 3.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. //===-- asan_poisoning.h ----------------------------------------*- 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. // Shadow memory poisoning by ASan RTL and by user application.
  12. //===----------------------------------------------------------------------===//
  13. #include "asan_interceptors.h"
  14. #include "asan_internal.h"
  15. #include "asan_mapping.h"
  16. #include "sanitizer_common/sanitizer_flags.h"
  17. #include "sanitizer_common/sanitizer_platform.h"
  18. namespace __asan {
  19. // Enable/disable memory poisoning.
  20. void SetCanPoisonMemory(bool value);
  21. bool CanPoisonMemory();
  22. // Poisons the shadow memory for "size" bytes starting from "addr".
  23. void PoisonShadow(uptr addr, uptr size, u8 value);
  24. // Poisons the shadow memory for "redzone_size" bytes starting from
  25. // "addr + size".
  26. void PoisonShadowPartialRightRedzone(uptr addr,
  27. uptr size,
  28. uptr redzone_size,
  29. u8 value);
  30. // Fast versions of PoisonShadow and PoisonShadowPartialRightRedzone that
  31. // assume that memory addresses are properly aligned. Use in
  32. // performance-critical code with care.
  33. ALWAYS_INLINE void FastPoisonShadow(uptr aligned_beg, uptr aligned_size,
  34. u8 value) {
  35. DCHECK(!value || CanPoisonMemory());
  36. #if SANITIZER_FUCHSIA
  37. __sanitizer_fill_shadow(aligned_beg, aligned_size, value,
  38. common_flags()->clear_shadow_mmap_threshold);
  39. #else
  40. uptr shadow_beg = MEM_TO_SHADOW(aligned_beg);
  41. uptr shadow_end =
  42. MEM_TO_SHADOW(aligned_beg + aligned_size - ASAN_SHADOW_GRANULARITY) + 1;
  43. // FIXME: Page states are different on Windows, so using the same interface
  44. // for mapping shadow and zeroing out pages doesn't "just work", so we should
  45. // probably provide higher-level interface for these operations.
  46. // For now, just memset on Windows.
  47. if (value || SANITIZER_WINDOWS == 1 ||
  48. shadow_end - shadow_beg < common_flags()->clear_shadow_mmap_threshold) {
  49. REAL(memset)((void*)shadow_beg, value, shadow_end - shadow_beg);
  50. } else {
  51. uptr page_size = GetPageSizeCached();
  52. uptr page_beg = RoundUpTo(shadow_beg, page_size);
  53. uptr page_end = RoundDownTo(shadow_end, page_size);
  54. if (page_beg >= page_end) {
  55. REAL(memset)((void *)shadow_beg, 0, shadow_end - shadow_beg);
  56. } else {
  57. if (page_beg != shadow_beg) {
  58. REAL(memset)((void *)shadow_beg, 0, page_beg - shadow_beg);
  59. }
  60. if (page_end != shadow_end) {
  61. REAL(memset)((void *)page_end, 0, shadow_end - page_end);
  62. }
  63. ReserveShadowMemoryRange(page_beg, page_end - 1, nullptr);
  64. }
  65. }
  66. #endif // SANITIZER_FUCHSIA
  67. }
  68. ALWAYS_INLINE void FastPoisonShadowPartialRightRedzone(
  69. uptr aligned_addr, uptr size, uptr redzone_size, u8 value) {
  70. DCHECK(CanPoisonMemory());
  71. bool poison_partial = flags()->poison_partial;
  72. u8 *shadow = (u8*)MEM_TO_SHADOW(aligned_addr);
  73. for (uptr i = 0; i < redzone_size; i += ASAN_SHADOW_GRANULARITY, shadow++) {
  74. if (i + ASAN_SHADOW_GRANULARITY <= size) {
  75. *shadow = 0; // fully addressable
  76. } else if (i >= size) {
  77. *shadow =
  78. (ASAN_SHADOW_GRANULARITY == 128) ? 0xff : value; // unaddressable
  79. } else {
  80. // first size-i bytes are addressable
  81. *shadow = poison_partial ? static_cast<u8>(size - i) : 0;
  82. }
  83. }
  84. }
  85. // Calls __sanitizer::ReleaseMemoryPagesToOS() on
  86. // [MemToShadow(p), MemToShadow(p+size)].
  87. void FlushUnneededASanShadowMemory(uptr p, uptr size);
  88. } // namespace __asan