summaryrefslogtreecommitdiff
path: root/libsanitizer/asan/asan_interceptors.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libsanitizer/asan/asan_interceptors.cc')
-rw-r--r--libsanitizer/asan/asan_interceptors.cc78
1 files changed, 45 insertions, 33 deletions
diff --git a/libsanitizer/asan/asan_interceptors.cc b/libsanitizer/asan/asan_interceptors.cc
index 5b544c87fcb..26daee1727c 100644
--- a/libsanitizer/asan/asan_interceptors.cc
+++ b/libsanitizer/asan/asan_interceptors.cc
@@ -25,38 +25,20 @@
namespace __asan {
-// Instruments read/write access to a single byte in memory.
-// On error calls __asan_report_error, which aborts the program.
-#define ACCESS_ADDRESS(address, isWrite) do { \
- if (!AddrIsInMem(address) || AddressIsPoisoned(address)) { \
- GET_CURRENT_PC_BP_SP; \
- __asan_report_error(pc, bp, sp, address, isWrite, /* access_size */ 1); \
- } \
-} while (0)
-
// We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
// and ASAN_WRITE_RANGE as macro instead of function so
// that no extra frames are created, and stack trace contains
// relevant information only.
-
-// Instruments read/write access to a memory range.
-// More complex implementation is possible, for now just
-// checking the first and the last byte of a range.
-#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \
- if (size > 0) { \
- uptr ptr = (uptr)(offset); \
- ACCESS_ADDRESS(ptr, isWrite); \
- ACCESS_ADDRESS(ptr + (size) - 1, isWrite); \
- } \
+// We check all shadow bytes.
+#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \
+ if (uptr __ptr = __asan_region_is_poisoned((uptr)(offset), size)) { \
+ GET_CURRENT_PC_BP_SP; \
+ __asan_report_error(pc, bp, sp, __ptr, isWrite, /* access_size */1); \
+ } \
} while (0)
-#define ASAN_READ_RANGE(offset, size) do { \
- ACCESS_MEMORY_RANGE(offset, size, false); \
-} while (0)
-
-#define ASAN_WRITE_RANGE(offset, size) do { \
- ACCESS_MEMORY_RANGE(offset, size, true); \
-} while (0)
+#define ASAN_READ_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, false)
+#define ASAN_WRITE_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, true);
// Behavior of functions like "memcpy" or "strcpy" is undefined
// if memory intervals overlap. We report error in this case.
@@ -69,7 +51,7 @@ static inline bool RangesOverlap(const char *offset1, uptr length1,
const char *offset1 = (const char*)_offset1; \
const char *offset2 = (const char*)_offset2; \
if (RangesOverlap(offset1, length1, offset2, length2)) { \
- GET_STACK_TRACE_HERE(kStackTraceMax); \
+ GET_STACK_TRACE_FATAL_HERE; \
ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \
offset2, length2, &stack); \
} \
@@ -96,6 +78,11 @@ static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
// ---------------------- Wrappers ---------------- {{{1
using namespace __asan; // NOLINT
+#define COMMON_INTERCEPTOR_WRITE_RANGE(ptr, size) ASAN_WRITE_RANGE(ptr, size)
+#define COMMON_INTERCEPTOR_READ_RANGE(ptr, size) ASAN_READ_RANGE(ptr, size)
+#define COMMON_INTERCEPTOR_ENTER(func, ...) ENSURE_ASAN_INITED()
+#include "sanitizer_common/sanitizer_common_interceptors.h"
+
static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
AsanThread *t = (AsanThread*)arg;
asanThreadRegistry().SetCurrent(t);
@@ -105,7 +92,7 @@ static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
#if ASAN_INTERCEPT_PTHREAD_CREATE
INTERCEPTOR(int, pthread_create, void *thread,
void *attr, void *(*start_routine)(void*), void *arg) {
- GET_STACK_TRACE_HERE(kStackTraceMax);
+ GET_STACK_TRACE_THREAD;
u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
asanThreadRegistry().RegisterThread(t);
@@ -175,6 +162,25 @@ INTERCEPTOR(void, siglongjmp, void *env, int val) {
}
#endif
+#if ASAN_INTERCEPT_PRCTL
+#define PR_SET_NAME 15
+INTERCEPTOR(int, prctl, int option,
+ unsigned long arg2, unsigned long arg3, // NOLINT
+ unsigned long arg4, unsigned long arg5) { // NOLINT
+ int res = REAL(prctl(option, arg2, arg3, arg4, arg5));
+ if (option == PR_SET_NAME) {
+ AsanThread *t = asanThreadRegistry().GetCurrent();
+ if (t) {
+ char buff[17];
+ internal_strncpy(buff, (char*)arg2, 16);
+ buff[16] = 0;
+ t->summary()->set_name(buff);
+ }
+ }
+ return res;
+}
+#endif
+
#if ASAN_INTERCEPT___CXA_THROW
INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
CHECK(REAL(__cxa_throw));
@@ -256,8 +262,8 @@ INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
// See http://llvm.org/bugs/show_bug.cgi?id=11763.
CHECK_RANGES_OVERLAP("memcpy", to, size, from, size);
}
- ASAN_WRITE_RANGE(from, size);
- ASAN_READ_RANGE(to, size);
+ ASAN_READ_RANGE(from, size);
+ ASAN_WRITE_RANGE(to, size);
}
#if MAC_INTERPOSE_FUNCTIONS
// Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
@@ -275,8 +281,8 @@ INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
}
ENSURE_ASAN_INITED();
if (flags()->replace_intrin) {
- ASAN_WRITE_RANGE(from, size);
- ASAN_READ_RANGE(to, size);
+ ASAN_READ_RANGE(from, size);
+ ASAN_WRITE_RANGE(to, size);
}
#if MAC_INTERPOSE_FUNCTIONS
// Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
@@ -621,7 +627,7 @@ INTERCEPTOR_WINAPI(DWORD, CreateThread,
void* security, uptr stack_size,
DWORD (__stdcall *start_routine)(void*), void* arg,
DWORD flags, void* tid) {
- GET_STACK_TRACE_HERE(kStackTraceMax);
+ GET_STACK_TRACE_THREAD;
u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
asanThreadRegistry().RegisterThread(t);
@@ -646,6 +652,9 @@ void InitializeAsanInterceptors() {
#if MAC_INTERPOSE_FUNCTIONS
return;
#endif
+
+ SANITIZER_COMMON_INTERCEPTORS_INIT;
+
// Intercept mem* functions.
ASAN_INTERCEPT_FUNC(memcmp);
ASAN_INTERCEPT_FUNC(memmove);
@@ -718,6 +727,9 @@ void InitializeAsanInterceptors() {
#if ASAN_INTERCEPT_SIGLONGJMP
ASAN_INTERCEPT_FUNC(siglongjmp);
#endif
+#if ASAN_INTERCEPT_PRCTL
+ ASAN_INTERCEPT_FUNC(prctl);
+#endif
// Intercept exception handling functions.
#if ASAN_INTERCEPT___CXA_THROW