From 69af4eecb85d8deb4b810f46033118b97f6190be Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 17 May 2016 11:17:54 +0200 Subject: [PATCH] re PR sanitizer/71160 (libasan: Backport support for malloc within dlsym) PR sanitizer/71160 * asan/asan_malloc_linux.cc: Cherry pick upstream r254395 and r269633. From-SVN: r236314 --- libsanitizer/ChangeLog | 6 ++++ libsanitizer/asan/asan_malloc_linux.cc | 43 ++++++++++++++++++++------ 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog index 1268507b92b..063846922b6 100644 --- a/libsanitizer/ChangeLog +++ b/libsanitizer/ChangeLog @@ -1,3 +1,9 @@ +2016-05-17 Jakub Jelinek + + PR sanitizer/71160 + * asan/asan_malloc_linux.cc: Cherry pick upstream r254395 + and r269633. + 2016-04-21 Maxim Ostapenko PR sanitizer/70624 diff --git a/libsanitizer/asan/asan_malloc_linux.cc b/libsanitizer/asan/asan_malloc_linux.cc index d03f1bb89c8..bfe72af69e6 100644 --- a/libsanitizer/asan/asan_malloc_linux.cc +++ b/libsanitizer/asan/asan_malloc_linux.cc @@ -24,39 +24,62 @@ // ---------------------- Replacement functions ---------------- {{{1 using namespace __asan; // NOLINT +static uptr allocated_for_dlsym; +static const uptr kDlsymAllocPoolSize = 1024; +static uptr alloc_memory_for_dlsym[kDlsymAllocPoolSize]; + +static bool IsInDlsymAllocPool(const void *ptr) { + uptr off = (uptr)ptr - (uptr)alloc_memory_for_dlsym; + return off < sizeof(alloc_memory_for_dlsym); +} + +static void *AllocateFromLocalPool(uptr size_in_bytes) { + uptr size_in_words = RoundUpTo(size_in_bytes, kWordSize) / kWordSize; + void *mem = (void*)&alloc_memory_for_dlsym[allocated_for_dlsym]; + allocated_for_dlsym += size_in_words; + CHECK_LT(allocated_for_dlsym, kDlsymAllocPoolSize); + return mem; +} + INTERCEPTOR(void, free, void *ptr) { GET_STACK_TRACE_FREE; + if (UNLIKELY(IsInDlsymAllocPool(ptr))) + return; asan_free(ptr, &stack, FROM_MALLOC); } INTERCEPTOR(void, cfree, void *ptr) { GET_STACK_TRACE_FREE; + if (UNLIKELY(IsInDlsymAllocPool(ptr))) + return; asan_free(ptr, &stack, FROM_MALLOC); } INTERCEPTOR(void*, malloc, uptr size) { + if (UNLIKELY(!asan_inited)) + // Hack: dlsym calls malloc before REAL(malloc) is retrieved from dlsym. + return AllocateFromLocalPool(size); GET_STACK_TRACE_MALLOC; return asan_malloc(size, &stack); } INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { - if (UNLIKELY(!asan_inited)) { + if (UNLIKELY(!asan_inited)) // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. - const uptr kCallocPoolSize = 1024; - static uptr calloc_memory_for_dlsym[kCallocPoolSize]; - static uptr allocated; - uptr size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize; - void *mem = (void*)&calloc_memory_for_dlsym[allocated]; - allocated += size_in_words; - CHECK(allocated < kCallocPoolSize); - return mem; - } + return AllocateFromLocalPool(nmemb * size); GET_STACK_TRACE_MALLOC; return asan_calloc(nmemb, size, &stack); } INTERCEPTOR(void*, realloc, void *ptr, uptr size) { GET_STACK_TRACE_MALLOC; + if (UNLIKELY(IsInDlsymAllocPool(ptr))) { + uptr offset = (uptr)ptr - (uptr)alloc_memory_for_dlsym; + uptr copy_size = Min(size, kDlsymAllocPoolSize - offset); + void *new_ptr = asan_malloc(size, &stack); + internal_memcpy(new_ptr, ptr, copy_size); + return new_ptr; + } return asan_realloc(ptr, size, &stack); } -- 2.30.2