[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