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