summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Samsonov <vonosmas@gmail.com>2014-09-17 17:56:15 +0000
committerAlexey Samsonov <vonosmas@gmail.com>2014-09-17 17:56:15 +0000
commit1947bf99217a233bc7f147de19738f77845ec8b8 (patch)
treebeb627e464b6661ede6ac5bbb56cc31350b0e9b9
parentd122211e60ec211e6cb0fb435ae2e6d38e1e5fda (diff)
downloadbcm5719-llvm-1947bf99217a233bc7f147de19738f77845ec8b8.tar.gz
bcm5719-llvm-1947bf99217a233bc7f147de19738f77845ec8b8.zip
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 llvm-svn: 217971
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_common.h2
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc22
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_win.cc5
-rw-r--r--compiler-rt/lib/sanitizer_common/tests/sanitizer_posix_test.cc18
-rw-r--r--compiler-rt/lib/ubsan/ubsan_diag.cc6
-rw-r--r--compiler-rt/test/ubsan/TestCases/TypeCheck/misaligned.cpp11
6 files changed, 63 insertions, 1 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h
index b265f297d8d..c85264aef88 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h
@@ -167,6 +167,8 @@ uptr ReadFileToBuffer(const char *file_name, char **buff,
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);
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc
index be613fe5600..12a8ff179bb 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc
@@ -166,6 +166,28 @@ void InstallDeadlySignalHandlers(SignalHandlerType handler) {
}
#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
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win.cc b/compiler-rt/lib/sanitizer_common/sanitizer_win.cc
index 9d578fe2c99..4ecfe850e46 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_win.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_win.cc
@@ -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
diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_posix_test.cc b/compiler-rt/lib/sanitizer_common/tests/sanitizer_posix_test.cc
index 035899c8302..56ce416141f 100644
--- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_posix_test.cc
+++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_posix_test.cc
@@ -18,6 +18,7 @@
#include "gtest/gtest.h"
#include <pthread.h>
+#include <sys/mman.h>
namespace __sanitizer {
@@ -57,6 +58,23 @@ TEST(SanitizerCommon, PthreadDestructorIterations) {
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
diff --git a/compiler-rt/lib/ubsan/ubsan_diag.cc b/compiler-rt/lib/ubsan/ubsan_diag.cc
index 4a03aa38577..ea2fa9b4424 100644
--- a/compiler-rt/lib/ubsan/ubsan_diag.cc
+++ b/compiler-rt/lib/ubsan/ubsan_diag.cc
@@ -222,9 +222,13 @@ static void renderMemorySnippet(const Decorator &Decor, MemoryLocation Loc,
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);
}
diff --git a/compiler-rt/test/ubsan/TestCases/TypeCheck/misaligned.cpp b/compiler-rt/test/ubsan/TestCases/TypeCheck/misaligned.cpp
index e319b76e04b..a31384019fa 100644
--- a/compiler-rt/test/ubsan/TestCases/TypeCheck/misaligned.cpp
+++ b/compiler-rt/test/ubsan/TestCases/TypeCheck/misaligned.cpp
@@ -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;
}
}
OpenPOWER on IntegriCloud