[compiler-rt] Make mmap-munmap interceptor fail earlier (PR #171295)

Honey Goyal via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 27 21:57:29 PST 2026


https://github.com/honeygoyal updated https://github.com/llvm/llvm-project/pull/171295

>From 4995f6536dbc55d36d1f7f8e4f3a330cf5a43e62 Mon Sep 17 00:00:00 2001
From: Honey Goyal <honey.goyal3 at ibm.com>
Date: Wed, 7 Jan 2026 11:56:09 +0000
Subject: [PATCH 1/3] [ASan][AIX] Fail early on mmap/munmap shadow intersection

---
 compiler-rt/lib/asan/asan_interceptors.cpp    | 117 +++++++++++++-----
 .../asan/TestCases/mmap_shadow_overlap.cpp    |  35 ++++++
 2 files changed, 124 insertions(+), 28 deletions(-)
 create mode 100644 compiler-rt/test/asan/TestCases/mmap_shadow_overlap.cpp

diff --git a/compiler-rt/lib/asan/asan_interceptors.cpp b/compiler-rt/lib/asan/asan_interceptors.cpp
index 02f0ffde72042..9e290b003a8d2 100644
--- a/compiler-rt/lib/asan/asan_interceptors.cpp
+++ b/compiler-rt/lib/asan/asan_interceptors.cpp
@@ -87,6 +87,25 @@ int OnExit() {
   return 0;
 }
 
+static inline bool RangeOverlaps(uptr beg, uptr end_excl, uptr seg_beg, uptr seg_end_incl) {
+  if (!seg_beg && !seg_end_incl) return false;
+  uptr seg_end_excl = seg_end_incl + 1;
+  return beg < seg_end_excl && end_excl > seg_beg;
+}
+
+static inline bool IntersectsShadowOrGap(uptr beg, uptr end_excl) {
+  // Check shadow regions
+  if (RangeOverlaps(beg, end_excl, kLowShadowBeg, kLowShadowEnd)) return true;
+  if (kMidShadowBeg && RangeOverlaps(beg, end_excl, kMidShadowBeg, kMidShadowEnd)) return true;
+  if (RangeOverlaps(beg, end_excl, kHighShadowBeg, kHighShadowEnd)) return true;
+
+  // Check shadow gaps
+  if (RangeOverlaps(beg, end_excl, kShadowGapBeg, kShadowGapEnd)) return true;
+  if (kShadowGap2Beg && RangeOverlaps(beg, end_excl, kShadowGap2Beg, kShadowGap2End)) return true;
+  if (kShadowGap3Beg && RangeOverlaps(beg, end_excl, kShadowGap3Beg, kShadowGap3End)) return true;
+
+  return false;
+}
 }  // namespace __asan
 
 // ---------------------- Wrappers ---------------- {{{1
@@ -157,46 +176,88 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void*)
     }
 
 template <class Mmap>
-static void* mmap_interceptor(Mmap real_mmap, void* addr, SIZE_T length,
+static void *mmap_interceptor(Mmap real_mmap, void *addr, SIZE_T length,
                               int prot, int flags, int fd, OFF64_T offset) {
-  void* res = real_mmap(addr, length, prot, flags, fd, offset);
-  if (length && res != (void*)-1) {
+  if (length == 0)
+    return real_mmap(addr, length, prot, flags, fd, offset);
+
+  uptr start = reinterpret_cast<uptr>(addr);
+  uptr end_excl;
+  if (UNLIKELY(__builtin_add_overflow(start, (uptr)length, &end_excl))) {
+   errno = errno_EINVAL;
+    return (void *)-1;
+  }
+
+  if (flags & map_fixed) {
+    if (__asan::IntersectsShadowOrGap(start, end_excl)) {
+      errno = errno_EINVAL;
+      return (void *)-1;
+    }
+    if (!AddrIsInMem(start) || !AddrIsInMem(end_excl - 1)) {
+      errno = errno_ENOMEM;
+      return (void *)-1;
+    }
+  } else {
+    if (addr && __asan::IntersectsShadowOrGap(start, start + 1))
+      addr = nullptr;
+  }
+
+  void *res = real_mmap(addr, length, prot, flags, fd, offset);
+  if (res != (void *)-1) {
     const uptr beg = reinterpret_cast<uptr>(res);
-    DCHECK(IsAligned(beg, GetPageSize()));
-    SIZE_T rounded_length = RoundUpTo(length, GetPageSize());
-    // Only unpoison shadow if it's an ASAN managed address.
-    if (AddrIsInMem(beg) && AddrIsInMem(beg + rounded_length - 1))
-      PoisonShadow(beg, RoundUpTo(length, GetPageSize()), 0);
+    const uptr page = GetPageSize();
+    const uptr sz = RoundUpTo(length, page);
+    if (AddrIsInMem(beg) && AddrIsInMem(beg + sz - 1)) {
+      PoisonShadow(beg, sz, 0);
+    }
   }
   return res;
 }
 
 template <class Munmap>
-static int munmap_interceptor(Munmap real_munmap, void* addr, SIZE_T length) {
-  // We should not tag if munmap fail, but it's to late to tag after
-  // real_munmap, as the pages could be mmaped by another thread.
+static int munmap_interceptor(Munmap real_munmap, void *addr, SIZE_T length) {
+  if (length == 0)
+    return real_munmap(addr, length);
+
   const uptr beg = reinterpret_cast<uptr>(addr);
-  if (length && IsAligned(beg, GetPageSize())) {
-    SIZE_T rounded_length = RoundUpTo(length, GetPageSize());
-    // Protect from unmapping the shadow.
-    if (AddrIsInMem(beg) && AddrIsInMem(beg + rounded_length - 1))
-      PoisonShadow(beg, rounded_length, 0);
+  uptr end_excl;
+  if (UNLIKELY(__builtin_add_overflow(beg, (uptr)length, &end_excl))) {
+    errno = errno_EINVAL;
+    return -1;
+  }
+
+  if ((AddrIsInMem(beg) || AddrIsInMem(end_excl - 1)) &&
+      (!AddrIsInMem(beg) || !AddrIsInMem(end_excl - 1))) {
+    errno = errno_EINVAL;
+    return -1;
+  }
+
+  int res = real_munmap(addr, length);
+
+  if (res == 0) {
+    const uptr page = GetPageSize();
+    const uptr aligned_beg = RoundDownTo(beg, page);
+    const uptr aligned_end = RoundUpTo(end_excl, page);
+    if (AddrIsInMem(aligned_beg) && AddrIsInMem(aligned_end - 1)) {
+      PoisonShadow(aligned_beg, aligned_end - aligned_beg, 0);
+    }
   }
-  return real_munmap(addr, length);
+  return res;
 }
 
-#  define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, length, prot, flags, \
-                                       fd, offset)                           \
-    do {                                                                     \
-      (void)(ctx);                                                           \
-      return mmap_interceptor(REAL(mmap), addr, sz, prot, flags, fd, off);   \
-    } while (false)
+#  define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, length, prot, flags,    \
+                                     fd, offset)                                \
+  do {                                                                          \
+    (void)(ctx);                                                                \
+    return mmap_interceptor(REAL(mmap), addr, length, prot, flags, fd, offset); \
+  } while (false)
+
+#  define COMMON_INTERCEPTOR_MUNMAP_IMPL(ctx, addr, length)                    \
+  do {                                                                         \
+    (void)(ctx);                                                               \
+    return munmap_interceptor(REAL(munmap), addr, length);                     \
+  } while (false)
 
-#  define COMMON_INTERCEPTOR_MUNMAP_IMPL(ctx, addr, length) \
-    do {                                                    \
-      (void)(ctx);                                          \
-      return munmap_interceptor(REAL(munmap), addr, sz);    \
-    } while (false)
 
 #  if CAN_SANITIZE_LEAKS
 #    define COMMON_INTERCEPTOR_STRERROR() \
diff --git a/compiler-rt/test/asan/TestCases/mmap_shadow_overlap.cpp b/compiler-rt/test/asan/TestCases/mmap_shadow_overlap.cpp
new file mode 100644
index 0000000000000..2e9996161e012
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/mmap_shadow_overlap.cpp
@@ -0,0 +1,35 @@
+// RUN: %clangxx_asan -O0 %s -o %t && %run %t
+
+// REQUIRES: system-aix
+
+#include <sys/mman.h>
+#include <errno.h>
+#include <stdio.h>
+#include <assert.h>
+
+#define ASAN_AIX_SHADOW_OFFSET 0x0a01000000000000ULL
+
+int main() {
+    size_t map_size = 4096;
+    void* addr = (void*)ASAN_AIX_SHADOW_OFFSET;
+    
+    // Attempt to map memory directly on top of the Shadow Memory
+    void* ptr = mmap(addr, map_size, PROT_READ | PROT_WRITE,
+                     MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+
+    // We expect this to FAIL because it overlaps shadow memory
+    if (ptr != MAP_FAILED) {
+        fprintf(stderr, "TEST FAILED: mmap should have failed but returned %p\n", ptr);
+        munmap(ptr, map_size);
+        return 1;
+    }
+
+    // We expect errno to be EINVAL (Invalid Argument)
+    if (errno != EINVAL) {
+        fprintf(stderr, "TEST FAILED: Expected errno=EINVAL (%d), got %d\n", EINVAL, errno);
+        return 1;
+    }
+
+    printf("TEST PASSED: mmap failed as expected.\n");
+    return 0;
+}
\ No newline at end of file

>From 752a33c2f8b94cecc1ec35148665c02fa41b7d92 Mon Sep 17 00:00:00 2001
From: Honey Goyal <honey.goyal3 at ibm.com>
Date: Thu, 15 Jan 2026 20:12:43 +0000
Subject: [PATCH 2/3] [asan] Make mmap/munmap interceptors reject shadow memory
 overlaps

Add validation in mmap/munmap interceptors to prevent MAP_FIXED from
overlapping ASan's shadow memory regions. This protects ASan's internal
structures from corruption.

- mmap rejects MAP_FIXED on shadow regions with EINVAL
- munmap validates partial application memory overlaps
- Generic implementation using existing shadow layout constants
- Tests use runtime shadow detection to work across platforms
---
 compiler-rt/lib/asan/asan_interceptors.cpp    | 79 +++++++++++-------
 .../asan/TestCases/mmap_shadow_overlap.cpp    | 83 ++++++++++++-------
 .../asan/TestCases/munmap_shadow_partial.cpp  | 33 ++++++++
 3 files changed, 137 insertions(+), 58 deletions(-)
 create mode 100644 compiler-rt/test/asan/TestCases/munmap_shadow_partial.cpp

diff --git a/compiler-rt/lib/asan/asan_interceptors.cpp b/compiler-rt/lib/asan/asan_interceptors.cpp
index 9e290b003a8d2..d4d205b96b9b1 100644
--- a/compiler-rt/lib/asan/asan_interceptors.cpp
+++ b/compiler-rt/lib/asan/asan_interceptors.cpp
@@ -87,25 +87,39 @@ int OnExit() {
   return 0;
 }
 
-static inline bool RangeOverlaps(uptr beg, uptr end_excl, uptr seg_beg, uptr seg_end_incl) {
-  if (!seg_beg && !seg_end_incl) return false;
+#  if SANITIZER_POSIX
+static inline bool RangeOverlaps(uptr beg, uptr end_excl, uptr seg_beg,
+                                 uptr seg_end_incl) {
+  if (!seg_beg && !seg_end_incl)
+    return false;
   uptr seg_end_excl = seg_end_incl + 1;
   return beg < seg_end_excl && end_excl > seg_beg;
 }
 
 static inline bool IntersectsShadowOrGap(uptr beg, uptr end_excl) {
   // Check shadow regions
-  if (RangeOverlaps(beg, end_excl, kLowShadowBeg, kLowShadowEnd)) return true;
-  if (kMidShadowBeg && RangeOverlaps(beg, end_excl, kMidShadowBeg, kMidShadowEnd)) return true;
-  if (RangeOverlaps(beg, end_excl, kHighShadowBeg, kHighShadowEnd)) return true;
+  if (RangeOverlaps(beg, end_excl, kLowShadowBeg, kLowShadowEnd))
+    return true;
+  if (kMidShadowBeg &&
+      RangeOverlaps(beg, end_excl, kMidShadowBeg, kMidShadowEnd))
+    return true;
+  if (RangeOverlaps(beg, end_excl, kHighShadowBeg, kHighShadowEnd))
+    return true;
 
   // Check shadow gaps
-  if (RangeOverlaps(beg, end_excl, kShadowGapBeg, kShadowGapEnd)) return true;
-  if (kShadowGap2Beg && RangeOverlaps(beg, end_excl, kShadowGap2Beg, kShadowGap2End)) return true;
-  if (kShadowGap3Beg && RangeOverlaps(beg, end_excl, kShadowGap3Beg, kShadowGap3End)) return true;
+  if (RangeOverlaps(beg, end_excl, kShadowGapBeg, kShadowGapEnd))
+    return true;
+  if (kShadowGap2Beg &&
+      RangeOverlaps(beg, end_excl, kShadowGap2Beg, kShadowGap2End))
+    return true;
+  if (kShadowGap3Beg &&
+      RangeOverlaps(beg, end_excl, kShadowGap3Beg, kShadowGap3End))
+    return true;
 
   return false;
 }
+#  endif  // SANITIZER_POSIX
+
 }  // namespace __asan
 
 // ---------------------- Wrappers ---------------- {{{1
@@ -176,34 +190,36 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void*)
     }
 
 template <class Mmap>
-static void *mmap_interceptor(Mmap real_mmap, void *addr, SIZE_T length,
+static void* mmap_interceptor(Mmap real_mmap, void* addr, SIZE_T length,
                               int prot, int flags, int fd, OFF64_T offset) {
   if (length == 0)
     return real_mmap(addr, length, prot, flags, fd, offset);
 
+#  if SANITIZER_POSIX
   uptr start = reinterpret_cast<uptr>(addr);
   uptr end_excl;
   if (UNLIKELY(__builtin_add_overflow(start, (uptr)length, &end_excl))) {
-   errno = errno_EINVAL;
-    return (void *)-1;
+    errno = errno_EINVAL;
+    return (void*)-1;
   }
 
   if (flags & map_fixed) {
     if (__asan::IntersectsShadowOrGap(start, end_excl)) {
       errno = errno_EINVAL;
-      return (void *)-1;
+      return (void*)-1;
     }
     if (!AddrIsInMem(start) || !AddrIsInMem(end_excl - 1)) {
       errno = errno_ENOMEM;
-      return (void *)-1;
+      return (void*)-1;
     }
   } else {
     if (addr && __asan::IntersectsShadowOrGap(start, start + 1))
       addr = nullptr;
   }
+#  endif  // SANITIZER_POSIX
 
-  void *res = real_mmap(addr, length, prot, flags, fd, offset);
-  if (res != (void *)-1) {
+  void* res = real_mmap(addr, length, prot, flags, fd, offset);
+  if (res != (void*)-1) {
     const uptr beg = reinterpret_cast<uptr>(res);
     const uptr page = GetPageSize();
     const uptr sz = RoundUpTo(length, page);
@@ -215,10 +231,11 @@ static void *mmap_interceptor(Mmap real_mmap, void *addr, SIZE_T length,
 }
 
 template <class Munmap>
-static int munmap_interceptor(Munmap real_munmap, void *addr, SIZE_T length) {
+static int munmap_interceptor(Munmap real_munmap, void* addr, SIZE_T length) {
   if (length == 0)
     return real_munmap(addr, length);
 
+#  if SANITIZER_POSIX
   const uptr beg = reinterpret_cast<uptr>(addr);
   uptr end_excl;
   if (UNLIKELY(__builtin_add_overflow(beg, (uptr)length, &end_excl))) {
@@ -226,11 +243,13 @@ static int munmap_interceptor(Munmap real_munmap, void *addr, SIZE_T length) {
     return -1;
   }
 
-  if ((AddrIsInMem(beg) || AddrIsInMem(end_excl - 1)) &&
-      (!AddrIsInMem(beg) || !AddrIsInMem(end_excl - 1))) {
+  bool beg_in_mem = AddrIsInMem(beg);
+  bool end_in_mem = AddrIsInMem(end_excl - 1);
+  if ((beg_in_mem || end_in_mem) && (beg_in_mem != end_in_mem)) {
     errno = errno_EINVAL;
     return -1;
   }
+#  endif  // SANITIZER_POSIX
 
   int res = real_munmap(addr, length);
 
@@ -245,19 +264,19 @@ static int munmap_interceptor(Munmap real_munmap, void *addr, SIZE_T length) {
   return res;
 }
 
-#  define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, length, prot, flags,    \
-                                     fd, offset)                                \
-  do {                                                                          \
-    (void)(ctx);                                                                \
-    return mmap_interceptor(REAL(mmap), addr, length, prot, flags, fd, offset); \
-  } while (false)
-
-#  define COMMON_INTERCEPTOR_MUNMAP_IMPL(ctx, addr, length)                    \
-  do {                                                                         \
-    (void)(ctx);                                                               \
-    return munmap_interceptor(REAL(munmap), addr, length);                     \
-  } while (false)
+#  define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, length, prot, flags, \
+                                       fd, offset)                           \
+    do {                                                                     \
+      (void)(ctx);                                                           \
+      return mmap_interceptor(REAL(mmap), addr, length, prot, flags, fd,     \
+                              offset);                                       \
+    } while (false)
 
+#  define COMMON_INTERCEPTOR_MUNMAP_IMPL(ctx, addr, length)  \
+    do {                                                     \
+      (void)(ctx);                                           \
+      return munmap_interceptor(REAL(munmap), addr, length); \
+    } while (false)
 
 #  if CAN_SANITIZE_LEAKS
 #    define COMMON_INTERCEPTOR_STRERROR() \
diff --git a/compiler-rt/test/asan/TestCases/mmap_shadow_overlap.cpp b/compiler-rt/test/asan/TestCases/mmap_shadow_overlap.cpp
index 2e9996161e012..d6f20e643496e 100644
--- a/compiler-rt/test/asan/TestCases/mmap_shadow_overlap.cpp
+++ b/compiler-rt/test/asan/TestCases/mmap_shadow_overlap.cpp
@@ -1,35 +1,62 @@
-// RUN: %clangxx_asan -O0 %s -o %t && %run %t
+// Test that mmap with MAP_FIXED fails when attempting to overlap shadow memory.
+//
+// RUN: %clangxx_asan %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+//
+// REQUIRES: !windows
 
-// REQUIRES: system-aix
-
-#include <sys/mman.h>
 #include <errno.h>
+#include <stdint.h>
 #include <stdio.h>
-#include <assert.h>
+#include <sys/mman.h>
 
-#define ASAN_AIX_SHADOW_OFFSET 0x0a01000000000000ULL
+extern "C" {
+void __asan_get_shadow_mapping(unsigned long *shadow_scale,
+                               unsigned long *shadow_offset);
+}
 
 int main() {
-    size_t map_size = 4096;
-    void* addr = (void*)ASAN_AIX_SHADOW_OFFSET;
-    
-    // Attempt to map memory directly on top of the Shadow Memory
-    void* ptr = mmap(addr, map_size, PROT_READ | PROT_WRITE,
-                     MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
-
-    // We expect this to FAIL because it overlaps shadow memory
-    if (ptr != MAP_FAILED) {
-        fprintf(stderr, "TEST FAILED: mmap should have failed but returned %p\n", ptr);
-        munmap(ptr, map_size);
-        return 1;
-    }
-
-    // We expect errno to be EINVAL (Invalid Argument)
-    if (errno != EINVAL) {
-        fprintf(stderr, "TEST FAILED: Expected errno=EINVAL (%d), got %d\n", EINVAL, errno);
-        return 1;
-    }
-
-    printf("TEST PASSED: mmap failed as expected.\n");
+  unsigned long scale = 0;
+  unsigned long offset = 0;
+  __asan_get_shadow_mapping(&scale, &offset);
+
+  if (offset == 0) {
+    fprintf(stderr, "SKIPPED\n");
     return 0;
-}
\ No newline at end of file
+  }
+
+  const size_t map_size = 4096;
+  void *shadow_addr = (void *)offset;
+
+  // MAP_FIXED on shadow memory should fail
+  void *ptr = mmap(shadow_addr, map_size, PROT_READ | PROT_WRITE,
+                   MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+  if (ptr != MAP_FAILED || errno != EINVAL) {
+    fprintf(stderr, "FAIL\n");
+    return 1;
+  }
+
+  // MAP_FIXED in middle of shadow should fail
+  void *mid_shadow = (void *)(offset + 0x100000);
+  errno = 0;
+  ptr = mmap(mid_shadow, map_size, PROT_READ | PROT_WRITE,
+             MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+  if (ptr != MAP_FAILED || errno != EINVAL) {
+    fprintf(stderr, "FAIL\n");
+    return 1;
+  }
+
+  // Normal mmap should succeed
+  errno = 0;
+  ptr = mmap(NULL, map_size, PROT_READ | PROT_WRITE,
+             MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  if (ptr == MAP_FAILED) {
+    fprintf(stderr, "FAIL\n");
+    return 1;
+  }
+  munmap(ptr, map_size);
+
+  fprintf(stderr, "PASS\n");
+  return 0;
+}
+// CHECK: {{^PASS$|^SKIPPED$}}
\ No newline at end of file
diff --git a/compiler-rt/test/asan/TestCases/munmap_shadow_partial.cpp b/compiler-rt/test/asan/TestCases/munmap_shadow_partial.cpp
new file mode 100644
index 0000000000000..b75462f2586c0
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/munmap_shadow_partial.cpp
@@ -0,0 +1,33 @@
+// Test that munmap correctly handles application memory regions.
+//
+// RUN: %clangxx_asan %s -o %t
+// RUN: %run %t 2>&1
+//
+// REQUIRES: !windows
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/mman.h>
+
+int main() {
+  const size_t map_size = 8192;
+
+  // Map application memory
+  void *ptr = mmap(NULL, map_size, PROT_READ | PROT_WRITE,
+                   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  if (ptr == MAP_FAILED) {
+    fprintf(stderr, "ERROR: mmap failed\n");
+    return 1;
+  }
+
+  // Normal munmap should succeed
+  int res = munmap(ptr, map_size);
+  if (res != 0) {
+    fprintf(stderr, "ERROR: munmap failed with errno=%d\n", errno);
+    return 1;
+  }
+
+  fprintf(stderr, "PASS\n");
+  // CHECK: PASS
+  return 0;
+}
\ No newline at end of file

>From 2d595f539362bae1fb1dd7587571eef9c36cf33b Mon Sep 17 00:00:00 2001
From: Honey Goyal <honey.goyal3 at ibm.com>
Date: Tue, 27 Jan 2026 09:02:51 +0000
Subject: [PATCH 3/3] Fixed Windows Build

---
 compiler-rt/lib/asan/asan_interceptors.cpp | 43 +++++++++-------------
 1 file changed, 18 insertions(+), 25 deletions(-)

diff --git a/compiler-rt/lib/asan/asan_interceptors.cpp b/compiler-rt/lib/asan/asan_interceptors.cpp
index d4d205b96b9b1..cabac26918ed5 100644
--- a/compiler-rt/lib/asan/asan_interceptors.cpp
+++ b/compiler-rt/lib/asan/asan_interceptors.cpp
@@ -192,17 +192,15 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void*)
 template <class Mmap>
 static void* mmap_interceptor(Mmap real_mmap, void* addr, SIZE_T length,
                               int prot, int flags, int fd, OFF64_T offset) {
+#  if SANITIZER_POSIX
   if (length == 0)
     return real_mmap(addr, length, prot, flags, fd, offset);
-
-#  if SANITIZER_POSIX
   uptr start = reinterpret_cast<uptr>(addr);
   uptr end_excl;
   if (UNLIKELY(__builtin_add_overflow(start, (uptr)length, &end_excl))) {
     errno = errno_EINVAL;
     return (void*)-1;
   }
-
   if (flags & map_fixed) {
     if (__asan::IntersectsShadowOrGap(start, end_excl)) {
       errno = errno_EINVAL;
@@ -212,37 +210,34 @@ static void* mmap_interceptor(Mmap real_mmap, void* addr, SIZE_T length,
       errno = errno_ENOMEM;
       return (void*)-1;
     }
-  } else {
-    if (addr && __asan::IntersectsShadowOrGap(start, start + 1))
-      addr = nullptr;
   }
 #  endif  // SANITIZER_POSIX
 
   void* res = real_mmap(addr, length, prot, flags, fd, offset);
-  if (res != (void*)-1) {
+  if (length && res != (void*)-1) {
     const uptr beg = reinterpret_cast<uptr>(res);
-    const uptr page = GetPageSize();
-    const uptr sz = RoundUpTo(length, page);
-    if (AddrIsInMem(beg) && AddrIsInMem(beg + sz - 1)) {
-      PoisonShadow(beg, sz, 0);
-    }
+    DCHECK(IsAligned(beg, GetPageSize()));
+    SIZE_T rounded_length = RoundUpTo(length, GetPageSize());
+    // Only unpoison shadow if it's an ASAN managed address.
+    if (AddrIsInMem(beg) && AddrIsInMem(beg + rounded_length - 1))
+      PoisonShadow(beg, RoundUpTo(length, GetPageSize()), 0);
   }
   return res;
 }
 
 template <class Munmap>
 static int munmap_interceptor(Munmap real_munmap, void* addr, SIZE_T length) {
+  const uptr beg = reinterpret_cast<uptr>(addr);
+
+#  if SANITIZER_POSIX
   if (length == 0)
     return real_munmap(addr, length);
 
-#  if SANITIZER_POSIX
-  const uptr beg = reinterpret_cast<uptr>(addr);
   uptr end_excl;
   if (UNLIKELY(__builtin_add_overflow(beg, (uptr)length, &end_excl))) {
     errno = errno_EINVAL;
     return -1;
   }
-
   bool beg_in_mem = AddrIsInMem(beg);
   bool end_in_mem = AddrIsInMem(end_excl - 1);
   if ((beg_in_mem || end_in_mem) && (beg_in_mem != end_in_mem)) {
@@ -251,17 +246,15 @@ static int munmap_interceptor(Munmap real_munmap, void* addr, SIZE_T length) {
   }
 #  endif  // SANITIZER_POSIX
 
-  int res = real_munmap(addr, length);
-
-  if (res == 0) {
-    const uptr page = GetPageSize();
-    const uptr aligned_beg = RoundDownTo(beg, page);
-    const uptr aligned_end = RoundUpTo(end_excl, page);
-    if (AddrIsInMem(aligned_beg) && AddrIsInMem(aligned_end - 1)) {
-      PoisonShadow(aligned_beg, aligned_end - aligned_beg, 0);
-    }
+  // We should not tag if munmap fail, but it's to late to tag after
+  // real_munmap, as the pages could be mmaped by another thread.
+  if (length && IsAligned(beg, GetPageSize())) {
+    SIZE_T rounded_length = RoundUpTo(length, GetPageSize());
+    // Protect from unmapping the shadow.
+    if (AddrIsInMem(beg) && AddrIsInMem(beg + rounded_length - 1))
+      PoisonShadow(beg, rounded_length, 0);
   }
-  return res;
+  return real_munmap(addr, length);
 }
 
 #  define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, length, prot, flags, \



More information about the llvm-commits mailing list