From 316d5c2986eec03e2ffea99f9facfb3dcb60dee7 Mon Sep 17 00:00:00 2001 From: Vyacheslav Cherkashin Date: Mon, 26 Aug 2019 18:34:02 +0300 Subject: [PATCH] libsanitizer: Make delete safe via 'pointer_is_mine' * libsanitizer/asan/asan_new_delete.cc: check pointers before calling forwarding. Part 2 for: 30255a5854a11a5e67c13b640d65a80411a34a39 This change will lead to possible failures inside glibc in cases of delete'ing wild pointers. In usual case ASan should handle this case and provide appropriate backtrace and error report, but this mode is not compatible with interceptor switching functional, so we explicitly disabling it. Change-Id: Ic1f2a70bbc156420c27067bae8eb5097bbc477d6 Signed-off-by: Vyacheslav Cherkashin Signed-off-by: Slava Barinov --- libsanitizer/asan/asan_malloc_linux.cc | 14 +++----------- libsanitizer/asan/asan_new_delete.cc | 16 ++++++++-------- libsanitizer/sanitizer_common/sanitizer_forward_calls.h | 8 ++++++++ 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/libsanitizer/asan/asan_malloc_linux.cc b/libsanitizer/asan/asan_malloc_linux.cc index 914c21a..59ad01e 100644 --- a/libsanitizer/asan/asan_malloc_linux.cc +++ b/libsanitizer/asan/asan_malloc_linux.cc @@ -46,10 +46,7 @@ INTERCEPTOR(void, free, void *ptr) { GET_STACK_TRACE_FREE; if (UNLIKELY(IsInDlsymAllocPool(ptr))) return; - if (UNLIKELY(!asan_pointer_is_mine(ptr))) { - REAL(free)(ptr); - return; - } + FORWARD_IF_MINE(free, ptr); asan_free(ptr, &stack, FROM_MALLOC); } @@ -57,10 +54,7 @@ INTERCEPTOR(void, cfree, void *ptr) { GET_STACK_TRACE_FREE; if (UNLIKELY(IsInDlsymAllocPool(ptr))) return; - if (UNLIKELY(!asan_pointer_is_mine(ptr))) { - REAL(cfree)(ptr); - return; - } + FORWARD_IF_MINE(cfree, ptr); asan_free(ptr, &stack, FROM_MALLOC); } @@ -102,9 +96,7 @@ INTERCEPTOR(void*, realloc, void *ptr, uptr size) { if (UNLIKELY(asan_init_is_running)) return AllocateFromLocalPool(size); ENSURE_ASAN_INITED(); - if (UNLIKELY(!asan_pointer_is_mine(ptr))) { - return REAL(realloc)(ptr, size); - } + FORWARD_IF_MINE(realloc, ptr, size); GET_STACK_TRACE_MALLOC; return asan_realloc(ptr, size, &stack); } diff --git a/libsanitizer/asan/asan_new_delete.cc b/libsanitizer/asan/asan_new_delete.cc index 53b4a63..97c8bd4 100644 --- a/libsanitizer/asan/asan_new_delete.cc +++ b/libsanitizer/asan/asan_new_delete.cc @@ -188,44 +188,44 @@ void operator delete[](void *ptr, size_t size) NOEXCEPT { #else // SANITIZER_CALLS_FORWARDING // operator delete(void*) INTERCEPTOR(void, _ZdlPv, void *ptr) { - MAYBE_FORWARD_TO_REAL(_ZdlPv, ptr); + FORWARD_IF_MINE(_ZdlPv, ptr); OPERATOR_DELETE_BODY(FROM_NEW); } // operator delete[](void*) INTERCEPTOR(void, _ZdaPv, void *ptr) { - MAYBE_FORWARD_TO_REAL(_ZdaPv, ptr); + FORWARD_IF_MINE(_ZdaPv, ptr); OPERATOR_DELETE_BODY(FROM_NEW_BR); } // operator delete(void*, std::nothrow_t const&) INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const& tag) { - MAYBE_FORWARD_TO_REAL(_ZdlPvRKSt9nothrow_t, ptr, tag); + FORWARD_IF_MINE(_ZdlPvRKSt9nothrow_t, ptr, tag); OPERATOR_DELETE_BODY(FROM_NEW); } // operator delete[](void*, std::nothrow_t const&) INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const& tag) { - MAYBE_FORWARD_TO_REAL(_ZdaPvRKSt9nothrow_t, ptr, tag); + FORWARD_IF_MINE(_ZdaPvRKSt9nothrow_t, ptr, tag); OPERATOR_DELETE_BODY(FROM_NEW_BR); } // operator delete(void*, unsigned long) INTERCEPTOR(void, _ZdlPvm, void *ptr, size_t size) { - MAYBE_FORWARD_TO_REAL(_ZdlPvm, ptr, size); + FORWARD_IF_MINE(_ZdlPvm, ptr, size); OPERATOR_SIZED_DELETE_BODY(FROM_NEW); } // operator delete(void*, unsigned int) INTERCEPTOR(void, _ZdlPvj, void *ptr, size_t size) { - MAYBE_FORWARD_TO_REAL(_ZdlPvj, ptr, size); + FORWARD_IF_MINE(_ZdlPvj, ptr, size); OPERATOR_SIZED_DELETE_BODY(FROM_NEW); } // operator delete[](void*, unsigned long) INTERCEPTOR(void, _ZdaPvm, void *ptr, size_t size) { - MAYBE_FORWARD_TO_REAL(_ZdaPvm, ptr, size); + FORWARD_IF_MINE(_ZdaPvm, ptr, size); OPERATOR_SIZED_DELETE_BODY(FROM_NEW_BR); } // operator delete[](void*, unsigned int) INTERCEPTOR(void, _ZdaPvj, void *ptr, size_t size) { - MAYBE_FORWARD_TO_REAL(_ZdaPvj, ptr, size); + FORWARD_IF_MINE(_ZdaPvj, ptr, size); OPERATOR_SIZED_DELETE_BODY(FROM_NEW_BR); } #endif diff --git a/libsanitizer/sanitizer_common/sanitizer_forward_calls.h b/libsanitizer/sanitizer_common/sanitizer_forward_calls.h index 92c29bc..646626b 100644 --- a/libsanitizer/sanitizer_common/sanitizer_forward_calls.h +++ b/libsanitizer/sanitizer_common/sanitizer_forward_calls.h @@ -49,9 +49,17 @@ bool ForwardCalls(); } \ } while (0) +#define FORWARD_IF_MINE(func, ptr, ...) \ + do { \ + if (UNLIKELY(!asan_pointer_is_mine(ptr))) { \ + return REAL(func)(ptr, ##__VA_ARGS__); \ + } \ + } while (0) + #else #define MAYBE_FORWARD_TO_REAL(func, ...) {} +#define FORWARD_IF_MINE(func, ...) {} #endif // SANITIZER_CALLS_FORWARDING -- 2.7.4