[compiler-rt] a34e702 - [ASAN] Add mmap and munmap interceptor in ASAN
Kirill Stoimenov via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 7 08:48:54 PDT 2023
Author: Kirill Stoimenov
Date: 2023-07-07T15:48:12Z
New Revision: a34e702aa16fde4cc76e9360d985a64e008e0b23
URL: https://github.com/llvm/llvm-project/commit/a34e702aa16fde4cc76e9360d985a64e008e0b23
DIFF: https://github.com/llvm/llvm-project/commit/a34e702aa16fde4cc76e9360d985a64e008e0b23.diff
LOG: [ASAN] Add mmap and munmap interceptor in ASAN
Reviewed By: vitalybuka
Differential Revision: https://reviews.llvm.org/D154659
Added:
compiler-rt/test/asan/TestCases/mapped_mem_interceptors.c
Modified:
compiler-rt/lib/asan/asan_interceptors.cpp
Removed:
################################################################################
diff --git a/compiler-rt/lib/asan/asan_interceptors.cpp b/compiler-rt/lib/asan/asan_interceptors.cpp
index 7aedefe81f95f5..b7e162c25094eb 100644
--- a/compiler-rt/lib/asan/asan_interceptors.cpp
+++ b/compiler-rt/lib/asan/asan_interceptors.cpp
@@ -23,6 +23,7 @@
#include "asan_suppressions.h"
#include "asan_thread.h"
#include "lsan/lsan_common.h"
+#include "sanitizer_common/sanitizer_errno.h"
#include "sanitizer_common/sanitizer_internal_defs.h"
#include "sanitizer_common/sanitizer_libc.h"
@@ -146,6 +147,48 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
*begin = *end = 0; \
}
+template <class Mmap>
+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) {
+ 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);
+ }
+ 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.
+ 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);
+ }
+ return real_munmap(addr, length);
+}
+
+# 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_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() \
__lsan::ScopedInterceptorDisabler disabler
diff --git a/compiler-rt/test/asan/TestCases/mapped_mem_interceptors.c b/compiler-rt/test/asan/TestCases/mapped_mem_interceptors.c
new file mode 100644
index 00000000000000..2df40fafbe7fad
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/mapped_mem_interceptors.c
@@ -0,0 +1,45 @@
+// Test for mmap/munmap interceptors.
+// RUN: %clang_asan %s -o %t
+// RUN: %run %t 2>&1
+
+#include <assert.h>
+#include <sanitizer/asan_interface.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+
+int main(int argc, char **argv) {
+ int size = 4096;
+ int val = 42;
+
+ // Get any mmaped pointer.
+ void *r =
+ mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
+ assert(r != MAP_FAILED);
+
+ // Make sure the memory is unpoisoned.
+ if (__asan_region_is_poisoned(r, size) != 0) {
+ fprintf(stderr, "Memory returned by mmap should be unpoisoned.\n");
+ abort();
+ }
+
+ // First munmmap and then mmap the same pointer using MAP_FIXED.
+ __asan_poison_memory_region(r, size);
+ munmap(r, size);
+ if (__asan_region_is_poisoned(r, size) != 0) {
+ fprintf(stderr, "Shadow memory was not cleaned by munmap.\n");
+ abort();
+ }
+ __asan_poison_memory_region(r, size);
+ void *p = mmap(r, size, PROT_READ | PROT_WRITE,
+ MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
+ assert(r == p);
+
+ // Make sure the memory is unpoisoned.
+ if (__asan_region_is_poisoned(r, size) != 0) {
+ fprintf(stderr, "Memory returned by mmap should be unpoisoned.\n");
+ abort();
+ }
+
+ return 0;
+}
More information about the llvm-commits
mailing list