diff options
| -rw-r--r-- | compiler-rt/lib/asan/asan_mapping.h | 33 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_rtl.cc | 15 | ||||
| -rw-r--r-- | compiler-rt/test/asan/TestCases/Linux/cuda_test.cc | 37 | 
3 files changed, 68 insertions, 17 deletions
diff --git a/compiler-rt/lib/asan/asan_mapping.h b/compiler-rt/lib/asan/asan_mapping.h index 5cbdd34d666..d8e60a4b34a 100644 --- a/compiler-rt/lib/asan/asan_mapping.h +++ b/compiler-rt/lib/asan/asan_mapping.h @@ -269,9 +269,25 @@ static inline bool AddrIsInMidMem(uptr a) {    return kMidMemBeg && a >= kMidMemBeg && a <= kMidMemEnd;  } +static inline bool AddrIsInShadowGap(uptr a) { +  PROFILE_ASAN_MAPPING(); +  if (kMidMemBeg) { +    if (a <= kShadowGapEnd) +      return SHADOW_OFFSET == 0 || a >= kShadowGapBeg; +    return (a >= kShadowGap2Beg && a <= kShadowGap2End) || +           (a >= kShadowGap3Beg && a <= kShadowGap3End); +  } +  // In zero-based shadow mode we treat addresses near zero as addresses +  // in shadow gap as well. +  if (SHADOW_OFFSET == 0) +    return a <= kShadowGapEnd; +  return a >= kShadowGapBeg && a <= kShadowGapEnd; +} +  static inline bool AddrIsInMem(uptr a) {    PROFILE_ASAN_MAPPING(); -  return AddrIsInLowMem(a) || AddrIsInMidMem(a) || AddrIsInHighMem(a); +  return AddrIsInLowMem(a) || AddrIsInMidMem(a) || AddrIsInHighMem(a) || +      (flags()->protect_shadow_gap == 0 && AddrIsInShadowGap(a));  }  static inline uptr MemToShadow(uptr p) { @@ -295,21 +311,6 @@ static inline bool AddrIsInShadow(uptr a) {    return AddrIsInLowShadow(a) || AddrIsInMidShadow(a) || AddrIsInHighShadow(a);  } -static inline bool AddrIsInShadowGap(uptr a) { -  PROFILE_ASAN_MAPPING(); -  if (kMidMemBeg) { -    if (a <= kShadowGapEnd) -      return SHADOW_OFFSET == 0 || a >= kShadowGapBeg; -    return (a >= kShadowGap2Beg && a <= kShadowGap2End) || -           (a >= kShadowGap3Beg && a <= kShadowGap3End); -  } -  // In zero-based shadow mode we treat addresses near zero as addresses -  // in shadow gap as well. -  if (SHADOW_OFFSET == 0) -    return a <= kShadowGapEnd; -  return a >= kShadowGapBeg && a <= kShadowGapEnd; -} -  static inline bool AddrIsAlignedByGranularity(uptr a) {    PROFILE_ASAN_MAPPING();    return (a & (SHADOW_GRANULARITY - 1)) == 0; diff --git a/compiler-rt/lib/asan/asan_rtl.cc b/compiler-rt/lib/asan/asan_rtl.cc index 462867be0e5..97ce9f84f4d 100644 --- a/compiler-rt/lib/asan/asan_rtl.cc +++ b/compiler-rt/lib/asan/asan_rtl.cc @@ -335,8 +335,21 @@ static void InitializeHighMemEnd() {  }  static void ProtectGap(uptr addr, uptr size) { -  if (!flags()->protect_shadow_gap) +  if (!flags()->protect_shadow_gap) { +    // The shadow gap is unprotected, so there is a chance that someone +    // is actually using this memory. Which means it needs a shadow... +    uptr GapShadowBeg = RoundDownTo(MEM_TO_SHADOW(addr), GetPageSizeCached()); +    uptr GapShadowEnd = +        RoundUpTo(MEM_TO_SHADOW(addr + size), GetPageSizeCached()) - 1; +    if (Verbosity()) +      Printf("protect_shadow_gap=0:" +             " not protecting shadow gap, allocating gap's shadow\n" +             "|| `[%p, %p]` || ShadowGap's shadow ||\n", GapShadowBeg, +             GapShadowEnd); +    ReserveShadowMemoryRange(GapShadowBeg, GapShadowEnd, +                             "unprotected gap shadow");      return; +  }    void *res = MmapFixedNoAccess(addr, size, "shadow gap");    if (addr == (uptr)res)      return; diff --git a/compiler-rt/test/asan/TestCases/Linux/cuda_test.cc b/compiler-rt/test/asan/TestCases/Linux/cuda_test.cc new file mode 100644 index 00000000000..e87f56b0c20 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/Linux/cuda_test.cc @@ -0,0 +1,37 @@ +// Emulate the behavior of the NVIDIA CUDA driver +// that mmaps memory inside the asan's shadow gap. +// +// REQUIRES: x86_64-target-arch +// +// RUN: %clangxx_asan %s -o %t +// RUN: not %env_asan_opts=protect_shadow_gap=1 %t 2>&1 | FileCheck %s  --check-prefix=CHECK-PROTECT1 +// RUN: not                                     %t 2>&1 | FileCheck %s  --check-prefix=CHECK-PROTECT1 +// RUN: not %env_asan_opts=protect_shadow_gap=0 %t 2>&1 | FileCheck %s  --check-prefix=CHECK-PROTECT0 +#include <assert.h> +#include <unistd.h> +#include <sys/mman.h> +#include <stdint.h> + +#include "sanitizer/asan_interface.h" + +int main(void) { +  uintptr_t Base = 0x200000000; +  uintptr_t Size = 0x1100000000; +  void *addr = +      mmap((void *)Base, Size, PROT_READ | PROT_WRITE, +           MAP_NORESERVE | MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0, 0); +  assert(addr == (void*)Base); +  // Make sure we can access memory in shadow gap. +  // W/o protect_shadow_gap=0 we should fail here. +  for (uintptr_t Addr = Base; Addr < Base + Size; Addr += Size / 100) +    *(char*)Addr = 1; +  // CHECK-PROTECT1: AddressSanitizer: SEGV on unknown address 0x0000bfff8000 + +  // Poison a part of gap's shadow: +  __asan_poison_memory_region((void*)Base, 4096); +  // Now we should fail with use-after-poison. +  *(char*)(Base + 1234) = 1; +  // CHECK-PROTECT0: AddressSanitizer: use-after-poison on address 0x0002000004d2 +} + +  | 

