asan_malloc_mac.cc revision 663c50134e01feefb6c5418c6ec7753be951c14f
1e5f5895bda30f374b0b51412fd4d837fa59aed66Alexey Samsonov//===-- asan_rtl.cc -------------------------------------------------------===// 21e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 31e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The LLVM Compiler Infrastructure 41e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 51e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is distributed under the University of Illinois Open Source 61e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// License. See LICENSE.TXT for details. 71e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 81e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===// 91e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker. 111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Mac-specific malloc interception. 131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===// 141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 15d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany#ifdef __APPLE__ 16d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany 171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <AvailabilityMacros.h> 181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <CoreFoundation/CFBase.h> 19d079db6dfbf3b0ec5fa1cc8d093e0dae6f970bf8Alexander Potapenko#include <dlfcn.h> 201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <malloc/malloc.h> 211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <setjmp.h> 221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_allocator.h" 241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_interceptors.h" 251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_internal.h" 26d079db6dfbf3b0ec5fa1cc8d093e0dae6f970bf8Alexander Potapenko#include "asan_mac.h" 27663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov#include "asan_report.h" 281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stack.h" 291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Similar code is used in Google Perftools, 311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// http://code.google.com/p/google-perftools. 321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// ---------------------- Replacement functions ---------------- {{{1 341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyusing namespace __asan; // NOLINT 351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 36e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko// TODO(glider): do we need both zones? 37e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenkostatic malloc_zone_t *system_malloc_zone = 0; 38e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenkostatic malloc_zone_t *system_purgeable_zone = 0; 3923a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenkostatic malloc_zone_t asan_zone; 40e205a9daec9ec4afed956cf5455889725b9192fbAlexander PotapenkoCFAllocatorRef cf_asan = 0; 41e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko 421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The free() implementation provided by OS X calls malloc_zone_from_ptr() 433f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany// to find the owner of |ptr|. If the result is 0, an invalid free() is 441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// reported. Our implementation falls back to asan_free() in this case 451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// in order to print an ASan-style report. 46e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko// 47e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko// For the objects created by _CFRuntimeCreateInstance a CFAllocatorRef is 48e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko// placed at the beginning of the allocated chunk and the pointer returned by 49e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko// our allocator is off by sizeof(CFAllocatorRef). This pointer can be then 50e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko// passed directly to free(), which will lead to errors. 51e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko// To overcome this we're checking whether |ptr-sizeof(CFAllocatorRef)| 52e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko// contains a pointer to our CFAllocator (assuming no other allocator is used). 53e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko// See http://code.google.com/p/address-sanitizer/issues/detail?id=70 for more 54e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko// info. 55e205a9daec9ec4afed956cf5455889725b9192fbAlexander PotapenkoINTERCEPTOR(void, free, void *ptr) { 561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_zone_t *zone = malloc_zone_from_ptr(ptr); 571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (zone) { 581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#if defined(MAC_OS_X_VERSION_10_6) && \ 591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if ((zone->version >= 6) && (zone->free_definite_size)) { 611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany zone->free_definite_size(zone, ptr, malloc_size(ptr)); 621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_zone_free(zone, ptr); 641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#else 661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_zone_free(zone, ptr); 671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#endif 681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 69cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->replace_cfallocator) { 70e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko // Make sure we're not hitting the previous page. This may be incorrect 71e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko // if ASan's malloc returns an address ending with 0xFF8, which will be 72e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko // then padded to a page boundary with a CFAllocatorRef. 73e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko uptr arith_ptr = (uptr)ptr; 74e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko if ((arith_ptr & 0xFFF) > sizeof(CFAllocatorRef)) { 75e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko CFAllocatorRef *saved = 76e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko (CFAllocatorRef*)(arith_ptr - sizeof(CFAllocatorRef)); 77e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko if ((*saved == cf_asan) && asan_mz_size(saved)) ptr = (void*)saved; 78e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko } 79e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko } 801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_FREE(ptr); 811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_free(ptr, &stack); 821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 8523a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenkonamespace __asan { 8623a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko void ReplaceCFAllocator(); 8723a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko} 8823a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko 89decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenko// We can't always replace the default CFAllocator with cf_asan right in 90decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenko// ReplaceSystemMalloc(), because it is sometimes called before 91decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenko// __CFInitialize(), when the default allocator is invalid and replacing it may 92decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenko// crash the program. Instead we wait for the allocator to initialize and jump 93decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenko// in just after __CFInitialize(). Nobody is going to allocate memory using 94decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenko// CFAllocators before that, so we won't miss anything. 95decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenko// 96decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenko// See http://code.google.com/p/address-sanitizer/issues/detail?id=87 97decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenko// and http://opensource.apple.com/source/CF/CF-550.43/CFRuntime.c 98decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander PotapenkoINTERCEPTOR(void, __CFInitialize) { 99cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov CHECK(flags()->replace_cfallocator); 10023a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko CHECK(asan_inited); 101decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenko REAL(__CFInitialize)(); 1020fedcd5abe8e9d51dc7177cf2fa239d9b83e270bAlexander Potapenko if (!cf_asan) ReplaceCFAllocator(); 103decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenko} 104decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenko 1051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace { 10623a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko 1071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// TODO(glider): the mz_* functions should be united with the Linux wrappers, 1081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// as they are basically copied from there. 1091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanysize_t mz_size(malloc_zone_t* zone, const void* ptr) { 1104fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov return asan_mz_size(ptr); 1111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *mz_malloc(malloc_zone_t *zone, size_t size) { 1141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!asan_inited) { 1151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(system_malloc_zone); 1161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return malloc_zone_malloc(system_malloc_zone, size); 1171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 1191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_malloc(size, &stack); 1201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *cf_malloc(CFIndex size, CFOptionFlags hint, void *info) { 1231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!asan_inited) { 1241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(system_malloc_zone); 1251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return malloc_zone_malloc(system_malloc_zone, size); 1261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 1281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_malloc(size, &stack); 1291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *mz_calloc(malloc_zone_t *zone, size_t nmemb, size_t size) { 1321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!asan_inited) { 13309672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. 1341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany const size_t kCallocPoolSize = 1024; 1353f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany static uptr calloc_memory_for_dlsym[kCallocPoolSize]; 1361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany static size_t allocated; 1371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany size_t size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize; 1381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *mem = (void*)&calloc_memory_for_dlsym[allocated]; 1391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany allocated += size_in_words; 1401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(allocated < kCallocPoolSize); 1411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return mem; 1421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 1441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_calloc(nmemb, size, &stack); 1451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *mz_valloc(malloc_zone_t *zone, size_t size) { 1481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!asan_inited) { 1491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(system_malloc_zone); 1501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return malloc_zone_valloc(system_malloc_zone, size); 1511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 1531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_memalign(kPageSize, size, &stack); 1541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 156663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov#define GET_ZONE_FOR_PTR(ptr) \ 157663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov malloc_zone_t *zone_ptr = malloc_zone_from_ptr(ptr); \ 158663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov const char *zone_name = (zone_ptr == 0) ? 0 : zone_ptr->zone_name 1591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1600aa794d78fbb6359f81025217559f1b03ff07999Alexander Potapenkovoid ALWAYS_INLINE free_common(void *context, void *ptr) { 1611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!ptr) return; 162cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (!flags()->mac_ignore_invalid_free || asan_mz_size(ptr)) { 1631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_FREE(ptr); 1641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_free(ptr, &stack); 1651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 1661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Let us just leak this memory for now. 1671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_FREE(ptr); 168663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov GET_ZONE_FOR_PTR(ptr); 169663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov WarnMacFreeUnallocated((uptr)ptr, (uptr)zone_ptr, zone_name, &stack); 1701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return; 1711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1740aa794d78fbb6359f81025217559f1b03ff07999Alexander Potapenko// TODO(glider): the allocation callbacks need to be refactored. 1750aa794d78fbb6359f81025217559f1b03ff07999Alexander Potapenkovoid mz_free(malloc_zone_t *zone, void *ptr) { 1760aa794d78fbb6359f81025217559f1b03ff07999Alexander Potapenko free_common(zone, ptr); 1770aa794d78fbb6359f81025217559f1b03ff07999Alexander Potapenko} 1780aa794d78fbb6359f81025217559f1b03ff07999Alexander Potapenko 1791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid cf_free(void *ptr, void *info) { 1800aa794d78fbb6359f81025217559f1b03ff07999Alexander Potapenko free_common(info, ptr); 1811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *mz_realloc(malloc_zone_t *zone, void *ptr, size_t size) { 1841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!ptr) { 1851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 1861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_malloc(size, &stack); 1871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 1884fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov if (asan_mz_size(ptr)) { 1891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 1901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_realloc(ptr, size, &stack); 1911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 1921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // We can't recover from reallocating an unknown address, because 1931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // this would require reading at most |size| bytes from 1941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // potentially unaccessible memory. 1951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_FREE(ptr); 196663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov GET_ZONE_FOR_PTR(ptr); 197663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov ReportMacMzReallocUnknown((uptr)ptr, (uptr)zone_ptr, zone_name, &stack); 1981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 2001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *cf_realloc(void *ptr, CFIndex size, CFOptionFlags hint, void *info) { 2031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!ptr) { 2041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 2051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_malloc(size, &stack); 2061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 2074fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov if (asan_mz_size(ptr)) { 2081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 2091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_realloc(ptr, size, &stack); 2101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 2111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // We can't recover from reallocating an unknown address, because 2121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // this would require reading at most |size| bytes from 2131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // potentially unaccessible memory. 2141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_FREE(ptr); 215663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov GET_ZONE_FOR_PTR(ptr); 216663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov ReportMacCfReallocUnknown((uptr)ptr, (uptr)zone_ptr, zone_name, &stack); 2171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 2181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 2191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid mz_destroy(malloc_zone_t* zone) { 2221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // A no-op -- we will not be destroyed! 223e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov AsanPrintf("mz_destroy() called -- ignoring\n"); 2241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // from AvailabilityMacros.h 2261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#if defined(MAC_OS_X_VERSION_10_6) && \ 2271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 2281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *mz_memalign(malloc_zone_t *zone, size_t align, size_t size) { 2291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!asan_inited) { 2301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(system_malloc_zone); 2311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return malloc_zone_memalign(system_malloc_zone, align, size); 2321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 2331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 2341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_memalign(align, size, &stack); 2351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 237c1ef2a0b8022f200f8bbb36641df866c4369876dDaniel Dunbar// This function is currently unused, and we build with -Werror. 238c1ef2a0b8022f200f8bbb36641df866c4369876dDaniel Dunbar#if 0 2391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid mz_free_definite_size(malloc_zone_t* zone, void *ptr, size_t size) { 2401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // TODO(glider): check that |size| is valid. 2411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany UNIMPLEMENTED(); 2421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#endif 244c1ef2a0b8022f200f8bbb36641df866c4369876dDaniel Dunbar#endif 2451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// malloc_introspection callbacks. I'm not clear on what all of these do. 2471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanykern_return_t mi_enumerator(task_t task, void *, 2481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany unsigned type_mask, vm_address_t zone_address, 2491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany memory_reader_t reader, 2501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany vm_range_recorder_t recorder) { 2511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Should enumerate all the pointers we have. Seems like a lot of work. 2521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return KERN_FAILURE; 2531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanysize_t mi_good_size(malloc_zone_t *zone, size_t size) { 2561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // I think it's always safe to return size, but we maybe could do better. 2571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return size; 2581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyboolean_t mi_check(malloc_zone_t *zone) { 2611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany UNIMPLEMENTED(); 2621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return true; 2631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid mi_print(malloc_zone_t *zone, boolean_t verbose) { 2661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany UNIMPLEMENTED(); 2671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return; 2681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid mi_log(malloc_zone_t *zone, void *address) { 2711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // I don't think we support anything like this 2721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid mi_force_lock(malloc_zone_t *zone) { 2754fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov asan_mz_force_lock(); 2761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid mi_force_unlock(malloc_zone_t *zone) { 2794fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov asan_mz_force_unlock(); 2801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 282c1ef2a0b8022f200f8bbb36641df866c4369876dDaniel Dunbar// This function is currently unused, and we build with -Werror. 283c1ef2a0b8022f200f8bbb36641df866c4369876dDaniel Dunbar#if 0 2841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid mi_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) { 2851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // TODO(csilvers): figure out how to fill these out 2861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // TODO(glider): port this from tcmalloc when ready. 2871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stats->blocks_in_use = 0; 2881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stats->size_in_use = 0; 2891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stats->max_size_in_use = 0; 2901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stats->size_allocated = 0; 2911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 292c1ef2a0b8022f200f8bbb36641df866c4369876dDaniel Dunbar#endif 2931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 294eeb719154538f38ffd54d8d3bfd8e113b97fe6a1Eli Friedman#if defined(MAC_OS_X_VERSION_10_6) && \ 295eeb719154538f38ffd54d8d3bfd8e113b97fe6a1Eli Friedman MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 2961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyboolean_t mi_zone_locked(malloc_zone_t *zone) { 2971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // UNIMPLEMENTED(); 2981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return false; 2991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 300eeb719154538f38ffd54d8d3bfd8e113b97fe6a1Eli Friedman#endif 3011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // unnamed namespace 3031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 304decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenkoextern int __CFRuntimeClassTableSize; 3051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 30723a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenkovoid ReplaceCFAllocator() { 30823a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko static CFAllocatorContext asan_context = { 30923a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko /*version*/ 0, /*info*/ &asan_zone, 31023a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko /*retain*/ 0, /*release*/ 0, 31123a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko /*copyDescription*/0, 31223a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko /*allocate*/ &cf_malloc, 31323a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko /*reallocate*/ &cf_realloc, 31423a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko /*deallocate*/ &cf_free, 31523a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko /*preferredSize*/ 0 }; 31675b19ebf25af204cf209d108997272822241d6daAlexander Potapenko if (!cf_asan) 31775b19ebf25af204cf209d108997272822241d6daAlexander Potapenko cf_asan = CFAllocatorCreate(kCFAllocatorUseContext, &asan_context); 31875b19ebf25af204cf209d108997272822241d6daAlexander Potapenko if (CFAllocatorGetDefault() != cf_asan) 31975b19ebf25af204cf209d108997272822241d6daAlexander Potapenko CFAllocatorSetDefault(cf_asan); 32023a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko} 32123a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko 3221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid ReplaceSystemMalloc() { 3231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany static malloc_introspection_t asan_introspection; 324ebb9702cff96192c6a6ea963037929ca7ed60eaeAlexander Potapenko // Ok to use internal_memset, these places are not performance-critical. 325ebb9702cff96192c6a6ea963037929ca7ed60eaeAlexander Potapenko internal_memset(&asan_introspection, 0, sizeof(asan_introspection)); 3261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_introspection.enumerator = &mi_enumerator; 3281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_introspection.good_size = &mi_good_size; 3291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_introspection.check = &mi_check; 3301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_introspection.print = &mi_print; 3311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_introspection.log = &mi_log; 3321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_introspection.force_lock = &mi_force_lock; 3331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_introspection.force_unlock = &mi_force_unlock; 3341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 335ebb9702cff96192c6a6ea963037929ca7ed60eaeAlexander Potapenko internal_memset(&asan_zone, 0, sizeof(malloc_zone_t)); 3361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Start with a version 4 zone which is used for OS X 10.4 and 10.5. 3381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.version = 4; 3391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.zone_name = "asan"; 3401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.size = &mz_size; 3411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.malloc = &mz_malloc; 3421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.calloc = &mz_calloc; 3431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.valloc = &mz_valloc; 3441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.free = &mz_free; 3451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.realloc = &mz_realloc; 3461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.destroy = &mz_destroy; 3473f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany asan_zone.batch_malloc = 0; 3483f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany asan_zone.batch_free = 0; 3491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.introspect = &asan_introspection; 3501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // from AvailabilityMacros.h 3521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#if defined(MAC_OS_X_VERSION_10_6) && \ 3531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 3541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Switch to version 6 on OSX 10.6 to support memalign. 3551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.version = 6; 3561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.free_definite_size = 0; 3571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.memalign = &mz_memalign; 3581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_introspection.zone_locked = &mi_zone_locked; 3591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Request the default purgable zone to force its creation. The 3611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // current default zone is registered with the purgable zone for 3621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // doing tiny and small allocs. Sadly, it assumes that the default 3631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // zone is the szone implementation from OS X and will crash if it 3641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // isn't. By creating the zone now, this will be true and changing 3651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // the default zone won't cause a problem. (OS X 10.6 and higher.) 3661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany system_purgeable_zone = malloc_default_purgeable_zone(); 3671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#endif 3681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Register the ASan zone. At this point, it will not be the 3701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // default zone. 3711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_zone_register(&asan_zone); 3721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Unregister and reregister the default zone. Unregistering swaps 3741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // the specified zone with the last one registered which for the 3751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // default zone makes the more recently registered zone the default 3761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // zone. The default zone is then re-registered to ensure that 3771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // allocations made from it earlier will be handled correctly. 3781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Things are not guaranteed to work that way, but it's how they work now. 3791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany system_malloc_zone = malloc_default_zone(); 3801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_zone_unregister(system_malloc_zone); 3811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_zone_register(system_malloc_zone); 3821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Make sure the default allocator was replaced. 3831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(malloc_default_zone() == &asan_zone); 3841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 385cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->replace_cfallocator) { 38623a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko // If __CFInitialize() hasn't been called yet, cf_asan will be created and 38723a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko // installed as the default allocator after __CFInitialize() finishes (see 38823a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko // the interceptor for __CFInitialize() above). Otherwise install cf_asan 38923a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko // right now. On both Snow Leopard and Lion __CFInitialize() calls 390bf9f6fbf015f687784e26f26570924be4ca3924fAlexander Potapenko // __CFAllocatorInitialize(), which initializes the _base._cfisa field of 391bf9f6fbf015f687784e26f26570924be4ca3924fAlexander Potapenko // the default allocators we check here. 392bf9f6fbf015f687784e26f26570924be4ca3924fAlexander Potapenko if (((CFRuntimeBase*)kCFAllocatorSystemDefault)->_cfisa) { 39323a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko ReplaceCFAllocator(); 394d079db6dfbf3b0ec5fa1cc8d093e0dae6f970bf8Alexander Potapenko } 3951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 3961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 398d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany 399d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany#endif // __APPLE__ 400