Mark unallocated/freed memory as inaccessible using ASan functionality
authorIvan Maidanski <ivmai@mail.ru>
Wed, 20 Dec 2017 07:11:54 +0000 (10:11 +0300)
committerIvan Maidanski <ivmai@mail.ru>
Fri, 22 Dec 2017 07:46:25 +0000 (10:46 +0300)
Note: to disable it, AO_NO_MALLOC_POISON should be defined by client.

* src/atomic_ops_malloc.c [AO_ADDRESS_SANITIZER && !AO_NO_MALLOC_POISON]
(__asan_poison_memory_region, __asan_unpoison_memory_region): Prototype.
* src/atomic_ops_malloc.c (ASAN_POISON_MEMORY_REGION,
ASAN_UNPOISON_MEMORY_REGION): New macro.
* src/atomic_ops_malloc.c (add_chunk_as): Call
ASAN_POISON_MEMORY_REGION() for each pushed region.
* src/atomic_ops_malloc.c (AO_malloc): Call
ASAN_UNPOISON_MEMORY_REGION() for the returned memory region.
* src/atomic_ops_malloc.c (AO_free): Call ASAN_POISON_MEMORY_REGION()
before pushing the freed region to AO_free_list.

src/atomic_ops_malloc.c

index 7cc7ada..acb00a0 100644 (file)
 # include <pthread.h>
 #endif
 
+#if defined(AO_ADDRESS_SANITIZER) && !defined(AO_NO_MALLOC_POISON)
+  /* #include "sanitizer/asan_interface.h" */
+  void __asan_poison_memory_region(void *, size_t);
+  void __asan_unpoison_memory_region(void *, size_t);
+# define ASAN_POISON_MEMORY_REGION(addr, size) \
+                __asan_poison_memory_region(addr, size)
+# define ASAN_UNPOISON_MEMORY_REGION(addr, size) \
+                __asan_unpoison_memory_region(addr, size)
+#else
+# define ASAN_POISON_MEMORY_REGION(addr, size) (void)0
+# define ASAN_UNPOISON_MEMORY_REGION(addr, size) (void)0
+#endif /* !AO_ADDRESS_SANITIZER */
+
 #if (defined(_WIN32_WCE) || defined(__MINGW32CE__)) && !defined(AO_HAVE_abort)
 # define abort() _exit(-1) /* there is no abort() in WinCE */
 #endif
@@ -244,6 +257,8 @@ static void add_chunk_as(void * chunk, unsigned log_sz)
   assert (CHUNK_SIZE >= sz);
   limit = (size_t)CHUNK_SIZE - sz;
   for (ofs = ALIGNMENT - sizeof(AO_t); ofs <= limit; ofs += sz) {
+    ASAN_POISON_MEMORY_REGION((char *)chunk + ofs + sizeof(AO_t),
+                              sz - sizeof(AO_t));
     AO_stack_push(&AO_free_list[log_sz], (AO_t *)((char *)chunk + ofs));
   }
 }
@@ -330,6 +345,7 @@ AO_malloc(size_t sz)
     fprintf(stderr, "%p: AO_malloc(%lu) = %p\n",
             (void *)pthread_self(), (unsigned long)sz, (void *)(result + 1));
 # endif
+  ASAN_UNPOISON_MEMORY_REGION(result + 1, sz);
   return result + 1;
 }
 
@@ -355,6 +371,7 @@ AO_free(void *p)
   if (AO_EXPECT_FALSE(log_sz > LOG_MAX_SIZE)) {
     AO_free_large(p);
   } else {
+    ASAN_POISON_MEMORY_REGION(base + 1, ((size_t)1 << log_sz) - sizeof(AO_t));
     AO_stack_push(AO_free_list + log_sz, base);
   }
 }