diff options
| author | Kostya Serebryany <kcc@google.com> | 2012-04-05 15:55:09 +0000 |
|---|---|---|
| committer | Kostya Serebryany <kcc@google.com> | 2012-04-05 15:55:09 +0000 |
| commit | 7a8f5e4d1edaba944ed5174d6d22da692dd9b7f0 (patch) | |
| tree | c24eafded12f3fd1c753443455c318e492893c23 | |
| parent | d6825173d35e2506682784f0981be506c5fd7db7 (diff) | |
| download | bcm5719-llvm-7a8f5e4d1edaba944ed5174d6d22da692dd9b7f0.tar.gz bcm5719-llvm-7a8f5e4d1edaba944ed5174d6d22da692dd9b7f0.zip | |
[asan] make __asan::Deallocate immune to racy double-free (issue #57)
llvm-svn: 154097
| -rw-r--r-- | compiler-rt/lib/asan/asan_allocator.cc | 12 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_internal.h | 1 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_posix.cc | 4 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_win.cc | 4 |
4 files changed, 17 insertions, 4 deletions
diff --git a/compiler-rt/lib/asan/asan_allocator.cc b/compiler-rt/lib/asan/asan_allocator.cc index 3797a0978cb..8c3cc00cf46 100644 --- a/compiler-rt/lib/asan/asan_allocator.cc +++ b/compiler-rt/lib/asan/asan_allocator.cc @@ -704,18 +704,22 @@ static void Deallocate(uint8_t *ptr, AsanStackTrace *stack) { // Printf("Deallocate %p\n", ptr); AsanChunk *m = PtrToChunk((uintptr_t)ptr); - if (m->chunk_state == CHUNK_QUARANTINE) { + + // Flip the state atomically to avoid race on double-free. + uint16_t old_chunk_state = AtomicExchange(&m->chunk_state, CHUNK_QUARANTINE); + + if (old_chunk_state == CHUNK_QUARANTINE) { Report("ERROR: AddressSanitizer attempting double-free on %p:\n", ptr); stack->PrintStack(); Describe((uintptr_t)ptr, 1); ShowStatsAndAbort(); - } else if (m->chunk_state != CHUNK_ALLOCATED) { + } else if (old_chunk_state != CHUNK_ALLOCATED) { Report("ERROR: AddressSanitizer attempting free on address which was not" " malloc()-ed: %p\n", ptr); stack->PrintStack(); ShowStatsAndAbort(); } - CHECK(m->chunk_state == CHUNK_ALLOCATED); + CHECK(old_chunk_state == CHUNK_ALLOCATED); CHECK(m->free_tid == AsanThread::kInvalidTid); CHECK(m->alloc_tid >= 0); AsanThread *t = asanThreadRegistry().GetCurrent(); @@ -731,7 +735,7 @@ static void Deallocate(uint8_t *ptr, AsanStackTrace *stack) { thread_stats.freed += m->used_size; thread_stats.freed_by_size[m->SizeClass()]++; - m->chunk_state = CHUNK_QUARANTINE; + CHECK(m->chunk_state == CHUNK_QUARANTINE); if (t) { AsanThreadLocalMallocStorage *ms = &t->malloc_storage(); CHECK(!m->next); diff --git a/compiler-rt/lib/asan/asan_internal.h b/compiler-rt/lib/asan/asan_internal.h index 39d3adf07a6..3a25cf285f9 100644 --- a/compiler-rt/lib/asan/asan_internal.h +++ b/compiler-rt/lib/asan/asan_internal.h @@ -187,6 +187,7 @@ void InstallSignalHandlers(); int GetPid(); uintptr_t GetThreadSelf(); int AtomicInc(int *a); +uint16_t AtomicExchange(uint16_t *a, uint16_t new_val); // Wrapper for TLS/TSD. void AsanTSDInit(void (*destructor)(void *tsd)); diff --git a/compiler-rt/lib/asan/asan_posix.cc b/compiler-rt/lib/asan/asan_posix.cc index 0ab09e615dc..03bd0579335 100644 --- a/compiler-rt/lib/asan/asan_posix.cc +++ b/compiler-rt/lib/asan/asan_posix.cc @@ -152,6 +152,10 @@ int AtomicInc(int *a) { #endif } +uint16_t AtomicExchange(uint16_t *a, uint16_t new_val) { + return __sync_lock_test_and_set(a, new_val); +} + void SortArray(uintptr_t *array, size_t size) { std::sort(array, array + size); } diff --git a/compiler-rt/lib/asan/asan_win.cc b/compiler-rt/lib/asan/asan_win.cc index 94f4d04a18a..baa8268b397 100644 --- a/compiler-rt/lib/asan/asan_win.cc +++ b/compiler-rt/lib/asan/asan_win.cc @@ -234,6 +234,10 @@ int AtomicInc(int *a) { return InterlockedExchangeAdd((LONG*)a, 1) + 1; } +uint16_t AtomicExchange(uint16_t *a, uint16_t new_val) { + return InterlockedExchange16(a, new_val); +} + const char* AsanGetEnv(const char* name) { static char env_buffer[32767] = {}; |

