[compiler-rt] r317943 - [asan] Use dynamic shadow on 32-bit Android.

Evgeniy Stepanov via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 10 14:27:48 PST 2017


Author: eugenis
Date: Fri Nov 10 14:27:48 2017
New Revision: 317943

URL: http://llvm.org/viewvc/llvm-project?rev=317943&view=rev
Log:
[asan] Use dynamic shadow on 32-bit Android.

Summary:
The following kernel change has moved ET_DYN base to 0x4000000 on arm32:
https://marc.info/?l=linux-kernel&m=149825162606848&w=2

Switch to dynamic shadow base to avoid such conflicts in the future.

Reserve shadow memory in an ifunc resolver, but don't use it in the instrumentation
until PR35221 is fixed. This will eventually let use save one load per function.

Reviewers: kcc

Subscribers: aemerson, srhines, kubamracek, kristof.beyls, hiraditya, llvm-commits

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

Added:
    compiler-rt/trunk/lib/asan/asan_premap_shadow.cc
    compiler-rt/trunk/lib/asan/asan_premap_shadow.h
Modified:
    compiler-rt/trunk/lib/asan/CMakeLists.txt
    compiler-rt/trunk/lib/asan/asan_init_version.h
    compiler-rt/trunk/lib/asan/asan_linux.cc
    compiler-rt/trunk/lib/asan/asan_mapping.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_fuchsia.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc

Modified: compiler-rt/trunk/lib/asan/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/CMakeLists.txt?rev=317943&r1=317942&r2=317943&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/asan/CMakeLists.txt Fri Nov 10 14:27:48 2017
@@ -21,6 +21,7 @@ set(ASAN_SOURCES
   asan_memory_profile.cc
   asan_poisoning.cc
   asan_posix.cc
+  asan_premap_shadow.cc
   asan_report.cc
   asan_rtl.cc
   asan_shadow_setup.cc

Modified: compiler-rt/trunk/lib/asan/asan_init_version.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_init_version.h?rev=317943&r1=317942&r2=317943&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_init_version.h (original)
+++ compiler-rt/trunk/lib/asan/asan_init_version.h Fri Nov 10 14:27:48 2017
@@ -15,6 +15,8 @@
 #ifndef ASAN_INIT_VERSION_H
 #define ASAN_INIT_VERSION_H
 
+#include "sanitizer_common/sanitizer_platform.h"
+
 extern "C" {
   // Every time the ASan ABI changes we also change the version number in the
   // __asan_init function name.  Objects built with incompatible ASan ABI
@@ -32,7 +34,12 @@ extern "C" {
   // v6=>v7: added 'odr_indicator' to __asan_global
   // v7=>v8: added '__asan_(un)register_image_globals' functions for dead
   //         stripping support on Mach-O platforms
+#if SANITIZER_WORDSIZE == 32 && SANITIZER_ANDROID
+  // v8=>v9: 32-bit Android switched to dynamic shadow
+  #define __asan_version_mismatch_check __asan_version_mismatch_check_v9
+#else
   #define __asan_version_mismatch_check __asan_version_mismatch_check_v8
+#endif
 }
 
 #endif  // ASAN_INIT_VERSION_H

Modified: compiler-rt/trunk/lib/asan/asan_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_linux.cc?rev=317943&r1=317942&r2=317943&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_linux.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_linux.cc Fri Nov 10 14:27:48 2017
@@ -17,6 +17,7 @@
 
 #include "asan_interceptors.h"
 #include "asan_internal.h"
+#include "asan_premap_shadow.h"
 #include "asan_thread.h"
 #include "sanitizer_common/sanitizer_flags.h"
 #include "sanitizer_common/sanitizer_freebsd.h"
@@ -81,10 +82,37 @@ void *AsanDoesNotSupportStaticLinkage()
   return &_DYNAMIC;  // defined in link.h
 }
 
+#if ASAN_PREMAP_SHADOW
 uptr FindDynamicShadowStart() {
-  UNREACHABLE("FindDynamicShadowStart is not available");
-  return 0;
+  uptr granularity = GetMmapGranularity();
+  uptr shadow_start = reinterpret_cast<uptr>(&__asan_shadow);
+  uptr shadow_size = PremapShadowSize();
+  UnmapOrDie((void *)(shadow_start - granularity), shadow_size + granularity);
+  // MmapNoAccess does not touch TotalMmap, but UnmapOrDie decreases it.
+  // Compensate.
+  IncreaseTotalMmap(shadow_size + granularity);
+  return shadow_start;
 }
+#else
+uptr FindDynamicShadowStart() {
+  uptr granularity = GetMmapGranularity();
+  uptr alignment = granularity * 8;
+  uptr left_padding = granularity;
+  uptr shadow_size = kHighShadowEnd + left_padding;
+  uptr map_size = shadow_size + alignment;
+
+  uptr map_start = (uptr)MmapNoAccess(map_size);
+  CHECK_NE(map_start, ~(uptr)0);
+
+  uptr shadow_start = RoundUpTo(map_start, alignment);
+  UnmapOrDie((void *)map_start, map_size);
+  // MmapNoAccess does not touch TotalMmap, but UnmapOrDie decreases it.
+  // Compensate.
+  IncreaseTotalMmap(map_size);
+
+  return shadow_start;
+}
+#endif
 
 void AsanApplyToGlobals(globals_op_fptr op, const void *needle) {
   UNIMPLEMENTED();

Modified: compiler-rt/trunk/lib/asan/asan_mapping.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_mapping.h?rev=317943&r1=317942&r2=317943&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_mapping.h (original)
+++ compiler-rt/trunk/lib/asan/asan_mapping.h Fri Nov 10 14:27:48 2017
@@ -156,7 +156,7 @@ static const u64 kWindowsShadowOffset32
 #  define SHADOW_OFFSET (0)
 #elif SANITIZER_WORDSIZE == 32
 #  if SANITIZER_ANDROID
-#    define SHADOW_OFFSET (0)
+#    define SHADOW_OFFSET __asan_shadow_memory_dynamic_address
 #  elif defined(__mips__)
 #    define SHADOW_OFFSET kMIPS32_ShadowOffset32
 #  elif SANITIZER_FREEBSD
@@ -200,6 +200,12 @@ static const u64 kWindowsShadowOffset32
 #  endif
 #endif
 
+#if SANITIZER_ANDROID && defined(__arm__)
+# define ASAN_PREMAP_SHADOW 1
+#else
+# define ASAN_PREMAP_SHADOW 0
+#endif
+
 #define SHADOW_GRANULARITY (1ULL << SHADOW_SCALE)
 #define MEM_TO_SHADOW(mem) (((mem) >> SHADOW_SCALE) + (SHADOW_OFFSET))
 

Added: compiler-rt/trunk/lib/asan/asan_premap_shadow.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_premap_shadow.cc?rev=317943&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_premap_shadow.cc (added)
+++ compiler-rt/trunk/lib/asan/asan_premap_shadow.cc Fri Nov 10 14:27:48 2017
@@ -0,0 +1,69 @@
+//===-- asan_premap_shadow.cc ---------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Reserve shadow memory with an ifunc resolver.
+//===----------------------------------------------------------------------===//
+
+#include "asan_mapping.h"
+
+#if ASAN_PREMAP_SHADOW
+
+#include "asan_premap_shadow.h"
+#include "sanitizer_common/sanitizer_posix.h"
+
+namespace __asan {
+
+// The code in this file needs to run in an unrelocated binary. It may not
+// access any external symbol, including its own non-hidden globals.
+
+// Conservative upper limit.
+uptr PremapShadowSize() {
+  return GetMaxVirtualAddress() >> SHADOW_SCALE;
+}
+
+// Returns an address aligned to 8 pages, such that one page on the left and
+// PremapShadowSize() bytes on the right of it are mapped r/o.
+uptr PremapShadow() {
+  uptr granularity = GetMmapGranularity();
+  uptr alignment = granularity * 8;
+  uptr left_padding = granularity;
+  uptr shadow_size = PremapShadowSize();
+  uptr map_size = shadow_size + left_padding + alignment;
+
+  uptr map_start = (uptr)MmapNoAccess(map_size);
+  CHECK_NE(map_start, ~(uptr)0);
+
+  uptr shadow_start = RoundUpTo(map_start + left_padding, alignment);
+  uptr shadow_end = shadow_start + shadow_size;
+  internal_munmap(reinterpret_cast<void *>(map_start),
+                  shadow_start - left_padding - map_start);
+  internal_munmap(reinterpret_cast<void *>(shadow_end),
+                  map_start + map_size - shadow_end);
+  return shadow_start;
+}
+
+} // namespace __asan
+
+extern "C" {
+decltype(__asan_shadow)* __asan_premap_shadow() {
+  // The resolver may be called multiple times. Map the shadow just once.
+  static uptr premapped_shadow = 0;
+  if (!premapped_shadow) premapped_shadow = __asan::PremapShadow();
+  return reinterpret_cast<decltype(__asan_shadow)*>(premapped_shadow);
+}
+
+// __asan_shadow is a "function" that has the same address as the first byte of
+// the shadow mapping.
+INTERFACE_ATTRIBUTE __attribute__((ifunc("__asan_premap_shadow"))) void
+__asan_shadow();
+}
+
+#endif // ASAN_PREMAP_SHADOW

Added: compiler-rt/trunk/lib/asan/asan_premap_shadow.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_premap_shadow.h?rev=317943&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_premap_shadow.h (added)
+++ compiler-rt/trunk/lib/asan/asan_premap_shadow.h Fri Nov 10 14:27:48 2017
@@ -0,0 +1,28 @@
+//===-- asan_mapping.h ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Premap shadow range with an ifunc resolver.
+//===----------------------------------------------------------------------===//
+
+
+#ifndef ASAN_PREMAP_SHADOW_H
+#define ASAN_PREMAP_SHADOW_H
+
+#if ASAN_PREMAP_SHADOW
+namespace __asan {
+// Conservative upper limit.
+uptr PremapShadowSize();
+}
+#endif
+
+extern "C" INTERFACE_ATTRIBUTE void __asan_shadow();
+
+#endif // ASAN_PREMAP_SHADOW_H

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h?rev=317943&r1=317942&r2=317943&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h Fri Nov 10 14:27:48 2017
@@ -73,6 +73,7 @@ INLINE uptr GetPageSizeCached() {
   return PageSizeCached;
 }
 uptr GetMmapGranularity();
+uptr GetMaxVirtualAddress();
 uptr GetMaxUserVirtualAddress();
 // Threads
 tid_t GetTid();

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h?rev=317943&r1=317942&r2=317943&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h Fri Nov 10 14:27:48 2017
@@ -34,7 +34,9 @@ struct CommonFlags {
 };
 
 // Functions to get/set global CommonFlags shared by all sanitizer runtimes:
-extern CommonFlags common_flags_dont_use;
+// FIXME: hidden needed for asan_premap_shadow. Consider building with
+// -fvisibility=hidden.
+extern CommonFlags common_flags_dont_use __attribute__((visibility("hidden")));
 inline const CommonFlags *common_flags() {
   return &common_flags_dont_use;
 }

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_fuchsia.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_fuchsia.cc?rev=317943&r1=317942&r2=317943&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_fuchsia.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_fuchsia.cc Fri Nov 10 14:27:48 2017
@@ -191,6 +191,10 @@ uptr GetMaxUserVirtualAddress() {
   return ShadowBounds.memory_limit - 1;
 }
 
+uptr GetMaxVirtualAddress() {
+  return GetMaxUserVirtualAddress();
+}
+
 static void *DoAnonymousMmapOrDie(uptr size, const char *mem_type,
                                   bool raw_report, bool die_for_nomem) {
   size = RoundUpTo(size, PAGE_SIZE);

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc?rev=317943&r1=317942&r2=317943&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc Fri Nov 10 14:27:48 2017
@@ -954,7 +954,7 @@ static uptr GetKernelAreaSize() {
 }
 #endif  // SANITIZER_WORDSIZE == 32
 
-uptr GetMaxUserVirtualAddress() {
+uptr GetMaxVirtualAddress() {
 #if SANITIZER_NETBSD && defined(__x86_64__)
   return 0x7f7ffffff000ULL;  // (0x00007f8000000000 - PAGE_SIZE)
 #elif SANITIZER_WORDSIZE == 64
@@ -978,15 +978,21 @@ uptr GetMaxUserVirtualAddress() {
 # if defined(__s390__)
   return (1ULL << 31) - 1;  // 0x7fffffff;
 # else
-  uptr res = (1ULL << 32) - 1;  // 0xffffffff;
-  if (!common_flags()->full_address_space)
-    res -= GetKernelAreaSize();
-  CHECK_LT(reinterpret_cast<uptr>(&res), res);
-  return res;
+  return (1ULL << 32) - 1;  // 0xffffffff;
 # endif
 #endif  // SANITIZER_WORDSIZE
 }
 
+uptr GetMaxUserVirtualAddress() {
+  uptr addr = GetMaxVirtualAddress();
+#if SANITIZER_WORDSIZE == 32 && !defined(__s390__)
+  if (!common_flags()->full_address_space)
+    addr -= GetKernelAreaSize();
+  CHECK_LT(reinterpret_cast<uptr>(&addr), addr);
+#endif
+  return addr;
+}
+
 uptr GetPageSize() {
 // Android post-M sysconf(_SC_PAGESIZE) crashes if called from .preinit_array.
 #if SANITIZER_ANDROID

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc?rev=317943&r1=317942&r2=317943&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc Fri Nov 10 14:27:48 2017
@@ -864,6 +864,10 @@ uptr GetMaxUserVirtualAddress() {
 #endif  // SANITIZER_WORDSIZE
 }
 
+uptr GetMaxVirtualAddress() {
+  return GetMaxUserVirtualAddress();
+}
+
 uptr FindAvailableMemoryRange(uptr shadow_size,
                               uptr alignment,
                               uptr left_padding,

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc?rev=317943&r1=317942&r2=317943&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc Fri Nov 10 14:27:48 2017
@@ -70,6 +70,10 @@ uptr GetMaxUserVirtualAddress() {
   return (uptr)si.lpMaximumApplicationAddress;
 }
 
+uptr GetMaxVirtualAddress() {
+  return GetMaxUserVirtualAddress();
+}
+
 bool FileExists(const char *filename) {
   return ::GetFileAttributesA(filename) != INVALID_FILE_ATTRIBUTES;
 }




More information about the llvm-commits mailing list