summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKostya Serebryany <kcc@google.com>2012-04-05 15:55:09 +0000
committerKostya Serebryany <kcc@google.com>2012-04-05 15:55:09 +0000
commit7a8f5e4d1edaba944ed5174d6d22da692dd9b7f0 (patch)
treec24eafded12f3fd1c753443455c318e492893c23
parentd6825173d35e2506682784f0981be506c5fd7db7 (diff)
downloadbcm5719-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.cc12
-rw-r--r--compiler-rt/lib/asan/asan_internal.h1
-rw-r--r--compiler-rt/lib/asan/asan_posix.cc4
-rw-r--r--compiler-rt/lib/asan/asan_win.cc4
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] = {};
OpenPOWER on IntegriCloud