[compiler-rt] r217971 - PR20721: Don't let UBSan print inaccessible memory

Alexey Samsonov vonosmas at gmail.com
Wed Sep 17 10:56:15 PDT 2014


Author: samsonov
Date: Wed Sep 17 12:56:15 2014
New Revision: 217971

URL: http://llvm.org/viewvc/llvm-project?rev=217971&view=rev
Log:
PR20721: Don't let UBSan print inaccessible memory

Summary:
UBSan needs to check if memory snippet it's going to print resides
in addressable memory. Similar check might be helpful in ASan with
dump_instruction_bytes option (see http://reviews.llvm.org/D5167).

Instead of scanning /proc/self/maps manually, delegate this check to
the OS kernel: try to write this memory in a syscall and assume that
memory is inaccessible if the syscall failed (e.g. with EFAULT).

Fixes PR20721.

Test Plan: compiler-rt test suite

Reviewers: eugenis, glider

Reviewed By: glider

Subscribers: emaste, ygribov, llvm-commits, glider, rsmith

Differential Revision: http://reviews.llvm.org/D5253

Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix_libcdep.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc
    compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_posix_test.cc
    compiler-rt/trunk/lib/ubsan/ubsan_diag.cc
    compiler-rt/trunk/test/ubsan/TestCases/TypeCheck/misaligned.cpp

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=217971&r1=217970&r2=217971&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h Wed Sep 17 12:56:15 2014
@@ -167,6 +167,8 @@ uptr ReadFileToBuffer(const char *file_n
 void *MapFileToMemory(const char *file_name, uptr *buff_size);
 void *MapWritableFileToMemory(void *addr, uptr size, uptr fd, uptr offset);
 
+bool IsAccessibleMemoryRange(uptr beg, uptr size);
+
 // Error report formatting.
 const char *StripPathPrefix(const char *filepath,
                             const char *strip_file_prefix);

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix_libcdep.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix_libcdep.cc?rev=217971&r1=217970&r2=217971&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix_libcdep.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix_libcdep.cc Wed Sep 17 12:56:15 2014
@@ -166,6 +166,28 @@ void InstallDeadlySignalHandlers(SignalH
 }
 #endif  // SANITIZER_GO
 
+bool IsAccessibleMemoryRange(uptr beg, uptr size) {
+  uptr page_size = GetPageSizeCached();
+  // Checking too large memory ranges is slow.
+  CHECK_LT(size, page_size * 10);
+  int sock_pair[2];
+  if (pipe(sock_pair))
+    return false;
+  uptr bytes_written =
+      internal_write(sock_pair[1], reinterpret_cast<void *>(beg), size);
+  int write_errno;
+  bool result;
+  if (internal_iserror(bytes_written, &write_errno)) {
+    CHECK_EQ(EFAULT, write_errno);
+    result = false;
+  } else {
+    result = (bytes_written == size);
+  }
+  internal_close(sock_pair[0]);
+  internal_close(sock_pair[1]);
+  return result;
+}
+
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_POSIX

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=217971&r1=217970&r2=217971&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc Wed Sep 17 12:56:15 2014
@@ -522,6 +522,11 @@ bool IsDeadlySignal(int signum) {
   return false;
 }
 
+bool IsAccessibleMemoryRange(uptr beg, uptr size) {
+  // FIXME: Actually implement this function.
+  return true;
+}
+
 }  // namespace __sanitizer
 
 #endif  // _WIN32

Modified: compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_posix_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_posix_test.cc?rev=217971&r1=217970&r2=217971&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_posix_test.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_posix_test.cc Wed Sep 17 12:56:15 2014
@@ -18,6 +18,7 @@
 #include "gtest/gtest.h"
 
 #include <pthread.h>
+#include <sys/mman.h>
 
 namespace __sanitizer {
 
@@ -57,6 +58,23 @@ TEST(SanitizerCommon, PthreadDestructorI
   EXPECT_FALSE(destructor_executed);
 }
 
+TEST(SanitizerCommon, IsAccessibleMemoryRange) {
+  const int page_size = GetPageSize();
+  uptr mem = (uptr)mmap(0, 3 * page_size, PROT_READ | PROT_WRITE,
+                        MAP_PRIVATE | MAP_ANON, -1, 0);
+  // Protect the middle page.
+  mprotect((void *)(mem + page_size), page_size, PROT_NONE);
+  EXPECT_TRUE(IsAccessibleMemoryRange(mem, page_size - 1));
+  EXPECT_TRUE(IsAccessibleMemoryRange(mem, page_size));
+  EXPECT_FALSE(IsAccessibleMemoryRange(mem, page_size + 1));
+  EXPECT_TRUE(IsAccessibleMemoryRange(mem + page_size - 1, 1));
+  EXPECT_FALSE(IsAccessibleMemoryRange(mem + page_size - 1, 2));
+  EXPECT_FALSE(IsAccessibleMemoryRange(mem + 2 * page_size - 1, 1));
+  EXPECT_TRUE(IsAccessibleMemoryRange(mem + 2 * page_size, page_size));
+  EXPECT_FALSE(IsAccessibleMemoryRange(mem, 3 * page_size));
+  EXPECT_FALSE(IsAccessibleMemoryRange(0x0, 2));
+}
+
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_POSIX

Modified: compiler-rt/trunk/lib/ubsan/ubsan_diag.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_diag.cc?rev=217971&r1=217970&r2=217971&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_diag.cc (original)
+++ compiler-rt/trunk/lib/ubsan/ubsan_diag.cc Wed Sep 17 12:56:15 2014
@@ -222,9 +222,13 @@ static void renderMemorySnippet(const De
     Min = __sanitizer::Min(Max - BytesToShow, OrigMin);
   Max = addNoOverflow(Min, BytesToShow);
 
+  if (!IsAccessibleMemoryRange(Min, Max - Min)) {
+    Printf("<memory cannot be printed>\n");
+    return;
+  }
+
   // Emit data.
   for (uptr P = Min; P != Max; ++P) {
-    // FIXME: Check that the address is readable before printing it.
     unsigned char C = *reinterpret_cast<const unsigned char*>(P);
     Printf("%s%02x", (P % 8 == 0) ? "  " : " ", C);
   }

Modified: compiler-rt/trunk/test/ubsan/TestCases/TypeCheck/misaligned.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/ubsan/TestCases/TypeCheck/misaligned.cpp?rev=217971&r1=217970&r2=217971&view=diff
==============================================================================
--- compiler-rt/trunk/test/ubsan/TestCases/TypeCheck/misaligned.cpp (original)
+++ compiler-rt/trunk/test/ubsan/TestCases/TypeCheck/misaligned.cpp Wed Sep 17 12:56:15 2014
@@ -8,6 +8,9 @@
 // RUN: %run %t n1 2>&1 | FileCheck %s --check-prefix=CHECK-NEW
 // RUN: UBSAN_OPTIONS=print_stacktrace=1 %run %t l1 2>&1 | FileCheck %s --check-prefix=CHECK-LOAD --check-prefix=CHECK-%os-STACK-LOAD
 
+// RUN: %clangxx -fsanitize=alignment -fno-sanitize-recover %s -O3 -o %t
+// RUN: not %run %t w1 2>&1 | FileCheck %s --check-prefix=CHECK-WILD
+
 #include <new>
 
 struct S {
@@ -23,6 +26,8 @@ int main(int, char **argv) {
   int *p = (int*)&c[4 + argv[1][1] - '0'];
   S *s = (S*)p;
 
+  void *wild = reinterpret_cast<void *>(0x123L);
+
   (void)*p; // ok!
 
   switch (argv[1][0]) {
@@ -74,5 +79,11 @@ int main(int, char **argv) {
     // CHECK-NEW-NEXT: {{^ 00 00 00 01 02 03 04  05}}
     // CHECK-NEW-NEXT: {{^             \^}}
     return (new (s) S)->k && 0;
+
+  case 'w':
+    // CHECK-WILD: misaligned.cpp:[[@LINE+3]]:35: runtime error: member access within misaligned address 0x000000000123 for type 'S', which requires 4 byte alignment
+    // CHECK-WILD-NEXT: 0x000000000123: note: pointer points here
+    // CHECK-WILD-NEXT: <memory cannot be printed>
+    return static_cast<S*>(wild)->k;
   }
 }





More information about the llvm-commits mailing list