[PATCH] Do not sanitize kernel area on 32-bit targets

Yury Gribov tetra2005 at gmail.com
Tue Mar 25 07:39:43 PDT 2014


  Updated based on Kostya's comments.

Hi kcc, glider, samsonov,

http://llvm-reviews.chandlerc.com/D3119

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D3119?vs=7951&id=8085#toc

Files:
  lib/sanitizer_common/sanitizer_posix.cc
  lib/asan/asan_mapping.h
  lib/asan/asan_rtl.cc
  test/asan/lit.cfg
  test/asan/CMakeLists.txt
  test/asan/TestCases/Linux/kernel-area.cc
  test/asan/lit.site.cfg.in

Index: lib/sanitizer_common/sanitizer_posix.cc
===================================================================
--- lib/sanitizer_common/sanitizer_posix.cc
+++ lib/sanitizer_common/sanitizer_posix.cc
@@ -22,13 +22,30 @@
 
 #include <sys/mman.h>
 
+#if SANITIZER_LINUX
+#include <sys/utsname.h>
+#endif
+
 namespace __sanitizer {
 
 // ------------- sanitizer_common.h
 uptr GetMmapGranularity() {
   return GetPageSize();
 }
 
+// Take care of unusable kernel area in top gigabyte
+static uptr GetKernelStartAddress() {
+#if SANITIZER_LINUX
+  // 64-bit Linux provides 32-bit apps with full address space
+  struct utsname uname_info;
+  return 0 == uname(&uname_info) && !internal_strstr(uname_info.machine, "64")
+    ? 1ULL << 30
+    : 0;
+#else
+  return 0;
+#endif  // SANITIZER_LINUX
+}
+
 uptr GetMaxVirtualAddress() {
 #if SANITIZER_WORDSIZE == 64
 # if defined(__powerpc64__)
@@ -44,8 +61,9 @@
   return (1ULL << 47) - 1;  // 0x00007fffffffffffUL;
 # endif
 #else  // SANITIZER_WORDSIZE == 32
-  // FIXME: We can probably lower this on Android?
-  return (1ULL << 32) - 1;  // 0xffffffff;
+  uptr res = (1ULL << 32) - 1;  // 0xffffffff;
+  res -= GetKernelStartAddress();
+  return res;
 #endif  // SANITIZER_WORDSIZE
 }
 
Index: lib/asan/asan_mapping.h
===================================================================
--- lib/asan/asan_mapping.h
+++ lib/asan/asan_mapping.h
@@ -43,13 +43,22 @@
 // || `[0x00007fff8000, 0x00008fff6fff]` || LowShadow  ||
 // || `[0x000000000000, 0x00007fff7fff]` || LowMem     ||
 //
-// Default Linux/i386 mapping:
+// Default Linux/i386 mapping on x86_64 machine:
 // || `[0x40000000, 0xffffffff]` || HighMem    ||
 // || `[0x28000000, 0x3fffffff]` || HighShadow ||
 // || `[0x24000000, 0x27ffffff]` || ShadowGap  ||
 // || `[0x20000000, 0x23ffffff]` || LowShadow  ||
 // || `[0x00000000, 0x1fffffff]` || LowMem     ||
 //
+// Default Linux/i386 mapping on i386 machine
+// (addresses starting with 0xc0000000 are reserved
+// for kernel and thus not sanitized):
+// || `[0x38000000, 0xbfffffff]` || HighMem    ||
+// || `[0x27000000, 0x37ffffff]` || HighShadow ||
+// || `[0x24000000, 0x26ffffff]` || ShadowGap  ||
+// || `[0x20000000, 0x23ffffff]` || LowShadow  ||
+// || `[0x00000000, 0x1fffffff]` || LowMem     ||
+//
 // Default Linux/MIPS mapping:
 // || `[0x2aaa8000, 0xffffffff]` || HighMem    ||
 // || `[0x0fffd000, 0x2aaa7fff]` || HighShadow ||
@@ -109,7 +118,8 @@
 
 #define kShadowGapBeg   (kLowShadowEnd ? kLowShadowEnd + 1 \
                                        : kZeroBaseShadowStart)
-#define kShadowGapEnd   ((kMidMemBeg ? kMidShadowBeg : kHighShadowBeg) - 1)
+#define kShadowGapEnd   ((kMidMemBeg ? kMidShadowBeg \
+                                     : MEM_TO_SHADOW(kHighShadowEnd + 1)) - 1)
 
 #define kShadowGap2Beg (kMidMemBeg ? kMidShadowEnd + 1 : 0)
 #define kShadowGap2End (kMidMemBeg ? kMidMemBeg - 1 : 0)
Index: lib/asan/asan_rtl.cc
===================================================================
--- lib/asan/asan_rtl.cc
+++ lib/asan/asan_rtl.cc
@@ -565,6 +565,8 @@
     ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd);
     // protect the gap.
     ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
+    // Allow accesses to unprotected part of address space
+    CHECK(kShadowGapEnd == kHighShadowBeg - 1);
   } else if (kMidMemBeg &&
       MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) &&
       MemoryRangeIsAvailable(kMidMemEnd + 1, kHighShadowEnd)) {
Index: test/asan/lit.cfg
===================================================================
--- test/asan/lit.cfg
+++ test/asan/lit.cfg
@@ -62,6 +62,7 @@
 
 # Define CHECK-%os to check for OS-dependent output.
 config.substitutions.append( ('CHECK-%os', ("CHECK-" + config.host_os)))
+config.substitutions.append( ('CHECK-%kernel_bits', ("CHECK-kernel-" + config.kernel_bits + "-bits")))
 
 config.available_features.add("asan-" + config.bits + "-bits")
 
Index: test/asan/CMakeLists.txt
===================================================================
--- test/asan/CMakeLists.txt
+++ test/asan/CMakeLists.txt
@@ -1,3 +1,5 @@
+include(AddLLVM)
+
 set(ASAN_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
 
 set(ASAN_TESTSUITES)
@@ -9,6 +11,7 @@
   get_filename_component(ASAN_TEST_LLVM_TOOLS_DIR ${CMAKE_C_COMPILER} PATH)
   set(ASAN_TEST_CONFIG_SUFFIX "-arm-android")
   set(ASAN_TEST_BITS "32")
+  set(ASAN_TEST_KERNEL_BITS "32")
   get_target_flags_for_arch(arm_android ASAN_TEST_TARGET_CFLAGS)
   configure_lit_site_cfg(
     ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
@@ -20,6 +23,7 @@
 if(CAN_TARGET_x86_64 OR CAN_TARGET_powerpc64)
   set(ASAN_TEST_CONFIG_SUFFIX "64")
   set(ASAN_TEST_BITS "64")
+  set(ASAN_TEST_KERNEL_BITS "64")
   set(ASAN_TEST_TARGET_CFLAGS ${TARGET_64_BIT_CFLAGS})
   configure_lit_site_cfg(
     ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
@@ -31,6 +35,11 @@
 if(CAN_TARGET_i386)
   set(ASAN_TEST_CONFIG_SUFFIX "32")
   set(ASAN_TEST_BITS "32")
+  if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64")
+    set(ASAN_TEST_KERNEL_BITS "64")
+  else()
+    set(ASAN_TEST_KERNEL_BITS "32")
+  endif()
   set(ASAN_TEST_TARGET_CFLAGS ${TARGET_32_BIT_CFLAGS})
   configure_lit_site_cfg(
     ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
Index: test/asan/TestCases/Linux/kernel-area.cc
===================================================================
--- test/asan/TestCases/Linux/kernel-area.cc
+++ test/asan/TestCases/Linux/kernel-area.cc
@@ -0,0 +1,19 @@
+// Test that kernel area is not sanitized on 32-bit machines.
+//
+// RUN: %clangxx_asan %s -o %t
+// RUN: ASAN_OPTIONS=verbosity=1 %t 2>&1 | FileCheck %s --check-prefix=CHECK-%kernel_bits
+//
+// CHECK-kernel-32-bits: || `[0x38000000, 0xbfffffff]` || HighMem    ||
+// CHECK-kernel-32-bits: || `[0x27000000, 0x37ffffff]` || HighShadow ||
+// CHECK-kernel-32-bits: || `[0x24000000, 0x26ffffff]` || ShadowGap  ||
+//
+// CHECK-kernel-64-bits: || `[0x40000000, 0xffffffff]` || HighMem    ||
+// CHECK-kernel-64-bits: || `[0x28000000, 0x3fffffff]` || HighShadow ||
+// CHECK-kernel-64-bits: || `[0x24000000, 0x27ffffff]` || ShadowGap  ||
+//
+// REQUIRES: asan-32-bits
+
+int main() {
+  return 0;
+}
+
Index: test/asan/lit.site.cfg.in
===================================================================
--- test/asan/lit.site.cfg.in
+++ test/asan/lit.site.cfg.in
@@ -9,6 +9,7 @@
 config.llvm_tools_dir = "@ASAN_TEST_LLVM_TOOLS_DIR@"
 config.bits = "@ASAN_TEST_BITS@"
 config.android = "@CAN_TARGET_arm_android@"
+config.kernel_bits = "@ASAN_TEST_KERNEL_BITS@"
 
 # Load common config for all compiler-rt lit tests.
 lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D3119.2.patch
Type: text/x-patch
Size: 6654 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140325/6a006f63/attachment.bin>


More information about the llvm-commits mailing list