diff options
author | Yury Gribov <y.gribov@samsung.com> | 2015-12-01 09:22:41 +0000 |
---|---|---|
committer | Yury Gribov <y.gribov@samsung.com> | 2015-12-01 09:22:41 +0000 |
commit | 627fd48e2b24f1356347de58c922cce6fe7ed3e1 (patch) | |
tree | d8351d0ced1344ab6f09fd7b5fa546e6c38ad7a9 /lib/asan | |
parent | 0c487bca5d972e4d58765f453d2f3c255d63164f (diff) |
[asan] Correctly release memory allocated during early startup.
Calloc interceptor initially allocates memory from temp buffer (to serve dlsyms called during asan_init). There is a chance that some non-instrumented library (or executable) has allocated memory with calloc before asan_init and got pointer from the same temporary buffer which later caused problems with free.
Inspired by https://github.com/google/sanitizers/issues/626
Differential Revision: http://reviews.llvm.org/D14979
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@254395 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/asan')
-rw-r--r-- | lib/asan/asan_malloc_linux.cc | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/lib/asan/asan_malloc_linux.cc b/lib/asan/asan_malloc_linux.cc index 46a6a9db4..d5089f9f7 100644 --- a/lib/asan/asan_malloc_linux.cc +++ b/lib/asan/asan_malloc_linux.cc @@ -26,13 +26,25 @@ // ---------------------- Replacement functions ---------------- {{{1 using namespace __asan; // NOLINT +static const uptr kCallocPoolSize = 1024; +static uptr calloc_memory_for_dlsym[kCallocPoolSize]; + +static bool IsInCallocPool(const void *ptr) { + sptr off = (sptr)ptr - (sptr)calloc_memory_for_dlsym; + return 0 <= off && off < (sptr)kCallocPoolSize; +} + INTERCEPTOR(void, free, void *ptr) { GET_STACK_TRACE_FREE; + if (UNLIKELY(IsInCallocPool(ptr))) + return; asan_free(ptr, &stack, FROM_MALLOC); } INTERCEPTOR(void, cfree, void *ptr) { GET_STACK_TRACE_FREE; + if (UNLIKELY(IsInCallocPool(ptr))) + return; asan_free(ptr, &stack, FROM_MALLOC); } @@ -44,8 +56,6 @@ INTERCEPTOR(void*, malloc, uptr size) { INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { 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]; @@ -59,6 +69,13 @@ INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { INTERCEPTOR(void*, realloc, void *ptr, uptr size) { GET_STACK_TRACE_MALLOC; + if (UNLIKELY(IsInCallocPool(ptr))) { + uptr offset = (uptr)ptr - (uptr)calloc_memory_for_dlsym; + uptr copy_size = Min(size, kCallocPoolSize - offset); + void *new_ptr = asan_malloc(size, &stack); + internal_memcpy(new_ptr, ptr, copy_size); + return new_ptr; + } return asan_realloc(ptr, size, &stack); } |