[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