[compiler-rt] db00fac - [compiler-rt][asan] decommit shadow memory for unmaps in fuchsia.

Marco Vanotti via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 21 11:08:12 PDT 2020


Author: Marco Vanotti
Date: 2020-07-21T11:07:47-07:00
New Revision: db00fac2a2b8641c20acd69b549943409145e8cb

URL: https://github.com/llvm/llvm-project/commit/db00fac2a2b8641c20acd69b549943409145e8cb
DIFF: https://github.com/llvm/llvm-project/commit/db00fac2a2b8641c20acd69b549943409145e8cb.diff

LOG: [compiler-rt][asan] decommit shadow memory for unmaps in fuchsia.

This CL allows asan allocator in fuchsia to decommit shadow memory
for memory allocated using mmap.

Big allocations in asan end up being allocated via `mmap` and freed with
`munmap`. However, when that memory is freed, asan returns the
corresponding shadow memory back to the OS via a call to
`ReleaseMemoryPagesToOs`.

In fuchsia, `ReleaseMemoryPagesToOs` is a no-op: to be able to free
memory back to the OS, you have to hold a handle to the vmo you want to
modify, which is tricky at the ReleaseMemoryPagesToOs level as that
function is not exclusively used for shadow memory.

The function `__sanitizer_fill_shadow` fills a given shadow memory range
with a specific value, and if that value is 0 (unpoison) and the memory
range is bigger than a threshold parameter, it will decommit that memory
if it is all zeroes.

This CL modifies the `FlushUnneededASanShadowMemory` function in
`asan_poisoning.cpp` to add a call to `__sanitizer_fill_shadow` with
value and threshold = 0. This way, all the unneeded shadow memory gets
returned back to the OS.

A test for this behavior can be found in fxrev.dev/391974

Differential Revision: https://reviews.llvm.org/D80355

Change-Id: Id6dd85693e78a222f0329d5b2201e0da753e01c0

Added: 
    

Modified: 
    compiler-rt/lib/asan/asan_fuchsia.cpp
    compiler-rt/lib/asan/asan_linux.cpp
    compiler-rt/lib/asan/asan_mac.cpp
    compiler-rt/lib/asan/asan_poisoning.cpp
    compiler-rt/lib/asan/asan_rtems.cpp
    compiler-rt/lib/asan/asan_win.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/asan/asan_fuchsia.cpp b/compiler-rt/lib/asan/asan_fuchsia.cpp
index 64f6dcbcefeb..ec15abfa0fe8 100644
--- a/compiler-rt/lib/asan/asan_fuchsia.cpp
+++ b/compiler-rt/lib/asan/asan_fuchsia.cpp
@@ -198,6 +198,10 @@ bool HandleDlopenInit() {
   return false;
 }
 
+void FlushUnneededASanShadowMemory(uptr p, uptr size) {
+  __sanitizer_fill_shadow(p, size, 0, 0);
+}
+
 }  // namespace __asan
 
 // These are declared (in extern "C") by <zircon/sanitizer.h>.

diff  --git a/compiler-rt/lib/asan/asan_linux.cpp b/compiler-rt/lib/asan/asan_linux.cpp
index aa93bbd79d13..fb1a442b3d43 100644
--- a/compiler-rt/lib/asan/asan_linux.cpp
+++ b/compiler-rt/lib/asan/asan_linux.cpp
@@ -114,6 +114,12 @@ void AsanApplyToGlobals(globals_op_fptr op, const void *needle) {
   UNIMPLEMENTED();
 }
 
+void FlushUnneededASanShadowMemory(uptr p, uptr size) {
+  // Since asan's mapping is compacting, the shadow chunk may be
+  // not page-aligned, so we only flush the page-aligned portion.
+  ReleaseMemoryPagesToOS(MemToShadow(p), MemToShadow(p + size));
+}
+
 #if SANITIZER_ANDROID
 // FIXME: should we do anything for Android?
 void AsanCheckDynamicRTPrereqs() {}

diff  --git a/compiler-rt/lib/asan/asan_mac.cpp b/compiler-rt/lib/asan/asan_mac.cpp
index 3182aacb0b5e..c6950547f089 100644
--- a/compiler-rt/lib/asan/asan_mac.cpp
+++ b/compiler-rt/lib/asan/asan_mac.cpp
@@ -89,6 +89,12 @@ void AsanApplyToGlobals(globals_op_fptr op, const void *needle) {
   op(globals, size / sizeof(__asan_global));
 }
 
+void FlushUnneededASanShadowMemory(uptr p, uptr size) {
+  // Since asan's mapping is compacting, the shadow chunk may be
+  // not page-aligned, so we only flush the page-aligned portion.
+  ReleaseMemoryPagesToOS(MemToShadow(p), MemToShadow(p + size));
+}
+
 void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
   UNIMPLEMENTED();
 }

diff  --git a/compiler-rt/lib/asan/asan_poisoning.cpp b/compiler-rt/lib/asan/asan_poisoning.cpp
index f3fbe684e2cb..44f872ef6190 100644
--- a/compiler-rt/lib/asan/asan_poisoning.cpp
+++ b/compiler-rt/lib/asan/asan_poisoning.cpp
@@ -62,12 +62,6 @@ struct ShadowSegmentEndpoint {
   }
 };
 
-void FlushUnneededASanShadowMemory(uptr p, uptr size) {
-  // Since asan's mapping is compacting, the shadow chunk may be
-  // not page-aligned, so we only flush the page-aligned portion.
-  ReleaseMemoryPagesToOS(MemToShadow(p), MemToShadow(p + size));
-}
-
 void AsanPoisonOrUnpoisonIntraObjectRedzone(uptr ptr, uptr size, bool poison) {
   uptr end = ptr + size;
   if (Verbosity()) {

diff  --git a/compiler-rt/lib/asan/asan_rtems.cpp b/compiler-rt/lib/asan/asan_rtems.cpp
index 2e5b2f0a3b21..ea0b4ad9db68 100644
--- a/compiler-rt/lib/asan/asan_rtems.cpp
+++ b/compiler-rt/lib/asan/asan_rtems.cpp
@@ -50,6 +50,12 @@ void AsanApplyToGlobals(globals_op_fptr op, const void *needle) {
   UNIMPLEMENTED();
 }
 
+void FlushUnneededASanShadowMemory(uptr p, uptr size) {
+  // Since asan's mapping is compacting, the shadow chunk may be
+  // not page-aligned, so we only flush the page-aligned portion.
+  ReleaseMemoryPagesToOS(MemToShadow(p), MemToShadow(p + size));
+}
+
 void AsanCheckDynamicRTPrereqs() {}
 void AsanCheckIncompatibleRT() {}
 void InitializeAsanInterceptors() {}

diff  --git a/compiler-rt/lib/asan/asan_win.cpp b/compiler-rt/lib/asan/asan_win.cpp
index fe635c2d5b6b..8044ae16ff9b 100644
--- a/compiler-rt/lib/asan/asan_win.cpp
+++ b/compiler-rt/lib/asan/asan_win.cpp
@@ -191,6 +191,12 @@ void AsanApplyToGlobals(globals_op_fptr op, const void *needle) {
   UNIMPLEMENTED();
 }
 
+void FlushUnneededASanShadowMemory(uptr p, uptr size) {
+  // Since asan's mapping is compacting, the shadow chunk may be
+  // not page-aligned, so we only flush the page-aligned portion.
+  ReleaseMemoryPagesToOS(MemToShadow(p), MemToShadow(p + size));
+}
+
 // ---------------------- TSD ---------------- {{{
 static bool tsd_key_inited = false;
 


        


More information about the llvm-commits mailing list