168d75effSDimitry Andric //===-- msan_allocator.cpp -------------------------- ---------------------===// 268d75effSDimitry Andric // 368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 668d75effSDimitry Andric // 768d75effSDimitry Andric //===----------------------------------------------------------------------===// 868d75effSDimitry Andric // 968d75effSDimitry Andric // This file is a part of MemorySanitizer. 1068d75effSDimitry Andric // 1168d75effSDimitry Andric // MemorySanitizer allocator. 1268d75effSDimitry Andric //===----------------------------------------------------------------------===// 1368d75effSDimitry Andric 1406c3fb27SDimitry Andric #include "msan_allocator.h" 1506c3fb27SDimitry Andric 1606c3fb27SDimitry Andric #include "msan.h" 1706c3fb27SDimitry Andric #include "msan_interface_internal.h" 1806c3fb27SDimitry Andric #include "msan_origin.h" 1906c3fb27SDimitry Andric #include "msan_poisoning.h" 2006c3fb27SDimitry Andric #include "msan_thread.h" 2168d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator.h" 2268d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator_checks.h" 2368d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator_interface.h" 2468d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator_report.h" 2568d75effSDimitry Andric #include "sanitizer_common/sanitizer_errno.h" 2668d75effSDimitry Andric 2768d75effSDimitry Andric namespace __msan { 2868d75effSDimitry Andric 2968d75effSDimitry Andric struct Metadata { 3068d75effSDimitry Andric uptr requested_size; 3168d75effSDimitry Andric }; 3268d75effSDimitry Andric 3368d75effSDimitry Andric struct MsanMapUnmapCallback { 3468d75effSDimitry Andric void OnMap(uptr p, uptr size) const {} 3506c3fb27SDimitry Andric void OnMapSecondary(uptr p, uptr size, uptr user_begin, 3606c3fb27SDimitry Andric uptr user_size) const {} 3768d75effSDimitry Andric void OnUnmap(uptr p, uptr size) const { 3868d75effSDimitry Andric __msan_unpoison((void *)p, size); 3968d75effSDimitry Andric 4068d75effSDimitry Andric // We are about to unmap a chunk of user memory. 4168d75effSDimitry Andric // Mark the corresponding shadow memory as not needed. 4268d75effSDimitry Andric uptr shadow_p = MEM_TO_SHADOW(p); 4368d75effSDimitry Andric ReleaseMemoryPagesToOS(shadow_p, shadow_p + size); 4468d75effSDimitry Andric if (__msan_get_track_origins()) { 4568d75effSDimitry Andric uptr origin_p = MEM_TO_ORIGIN(p); 4668d75effSDimitry Andric ReleaseMemoryPagesToOS(origin_p, origin_p + size); 4768d75effSDimitry Andric } 4868d75effSDimitry Andric } 4968d75effSDimitry Andric }; 5068d75effSDimitry Andric 5168d75effSDimitry Andric #if defined(__mips64) 5268d75effSDimitry Andric static const uptr kMaxAllowedMallocSize = 2UL << 30; 5368d75effSDimitry Andric 5468d75effSDimitry Andric struct AP32 { 5568d75effSDimitry Andric static const uptr kSpaceBeg = 0; 5668d75effSDimitry Andric static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; 5768d75effSDimitry Andric static const uptr kMetadataSize = sizeof(Metadata); 5868d75effSDimitry Andric typedef __sanitizer::CompactSizeClassMap SizeClassMap; 5968d75effSDimitry Andric static const uptr kRegionSizeLog = 20; 6068d75effSDimitry Andric using AddressSpaceView = LocalAddressSpaceView; 6168d75effSDimitry Andric typedef MsanMapUnmapCallback MapUnmapCallback; 6268d75effSDimitry Andric static const uptr kFlags = 0; 6368d75effSDimitry Andric }; 6468d75effSDimitry Andric typedef SizeClassAllocator32<AP32> PrimaryAllocator; 6568d75effSDimitry Andric #elif defined(__x86_64__) 66bdd1243dSDimitry Andric #if SANITIZER_NETBSD || SANITIZER_LINUX 6768d75effSDimitry Andric static const uptr kAllocatorSpace = 0x700000000000ULL; 6868d75effSDimitry Andric #else 6968d75effSDimitry Andric static const uptr kAllocatorSpace = 0x600000000000ULL; 7068d75effSDimitry Andric #endif 7168d75effSDimitry Andric static const uptr kMaxAllowedMallocSize = 8UL << 30; 7268d75effSDimitry Andric 7368d75effSDimitry Andric struct AP64 { // Allocator64 parameters. Deliberately using a short name. 7468d75effSDimitry Andric static const uptr kSpaceBeg = kAllocatorSpace; 7568d75effSDimitry Andric static const uptr kSpaceSize = 0x40000000000; // 4T. 7668d75effSDimitry Andric static const uptr kMetadataSize = sizeof(Metadata); 7768d75effSDimitry Andric typedef DefaultSizeClassMap SizeClassMap; 7868d75effSDimitry Andric typedef MsanMapUnmapCallback MapUnmapCallback; 7968d75effSDimitry Andric static const uptr kFlags = 0; 8068d75effSDimitry Andric using AddressSpaceView = LocalAddressSpaceView; 8168d75effSDimitry Andric }; 8268d75effSDimitry Andric 8368d75effSDimitry Andric typedef SizeClassAllocator64<AP64> PrimaryAllocator; 8468d75effSDimitry Andric 8506c3fb27SDimitry Andric #elif defined(__loongarch_lp64) 8606c3fb27SDimitry Andric const uptr kAllocatorSpace = 0x700000000000ULL; 8706c3fb27SDimitry Andric const uptr kMaxAllowedMallocSize = 8UL << 30; 8806c3fb27SDimitry Andric 8906c3fb27SDimitry Andric struct AP64 { // Allocator64 parameters. Deliberately using a short name. 9006c3fb27SDimitry Andric static const uptr kSpaceBeg = kAllocatorSpace; 9106c3fb27SDimitry Andric static const uptr kSpaceSize = 0x40000000000; // 4T. 9206c3fb27SDimitry Andric static const uptr kMetadataSize = sizeof(Metadata); 9306c3fb27SDimitry Andric typedef DefaultSizeClassMap SizeClassMap; 9406c3fb27SDimitry Andric typedef MsanMapUnmapCallback MapUnmapCallback; 9506c3fb27SDimitry Andric static const uptr kFlags = 0; 9606c3fb27SDimitry Andric using AddressSpaceView = LocalAddressSpaceView; 9706c3fb27SDimitry Andric }; 9806c3fb27SDimitry Andric 9906c3fb27SDimitry Andric typedef SizeClassAllocator64<AP64> PrimaryAllocator; 10006c3fb27SDimitry Andric 10168d75effSDimitry Andric #elif defined(__powerpc64__) 10268d75effSDimitry Andric static const uptr kMaxAllowedMallocSize = 2UL << 30; // 2G 10368d75effSDimitry Andric 10468d75effSDimitry Andric struct AP64 { // Allocator64 parameters. Deliberately using a short name. 10568d75effSDimitry Andric static const uptr kSpaceBeg = 0x300000000000; 10668d75effSDimitry Andric static const uptr kSpaceSize = 0x020000000000; // 2T. 10768d75effSDimitry Andric static const uptr kMetadataSize = sizeof(Metadata); 10868d75effSDimitry Andric typedef DefaultSizeClassMap SizeClassMap; 10968d75effSDimitry Andric typedef MsanMapUnmapCallback MapUnmapCallback; 11068d75effSDimitry Andric static const uptr kFlags = 0; 11168d75effSDimitry Andric using AddressSpaceView = LocalAddressSpaceView; 11268d75effSDimitry Andric }; 11368d75effSDimitry Andric 11468d75effSDimitry Andric typedef SizeClassAllocator64<AP64> PrimaryAllocator; 1155ffd83dbSDimitry Andric #elif defined(__s390x__) 1165ffd83dbSDimitry Andric static const uptr kMaxAllowedMallocSize = 2UL << 30; // 2G 1175ffd83dbSDimitry Andric 1185ffd83dbSDimitry Andric struct AP64 { // Allocator64 parameters. Deliberately using a short name. 1195ffd83dbSDimitry Andric static const uptr kSpaceBeg = 0x440000000000; 1205ffd83dbSDimitry Andric static const uptr kSpaceSize = 0x020000000000; // 2T. 1215ffd83dbSDimitry Andric static const uptr kMetadataSize = sizeof(Metadata); 1225ffd83dbSDimitry Andric typedef DefaultSizeClassMap SizeClassMap; 1235ffd83dbSDimitry Andric typedef MsanMapUnmapCallback MapUnmapCallback; 1245ffd83dbSDimitry Andric static const uptr kFlags = 0; 1255ffd83dbSDimitry Andric using AddressSpaceView = LocalAddressSpaceView; 1265ffd83dbSDimitry Andric }; 1275ffd83dbSDimitry Andric 1285ffd83dbSDimitry Andric typedef SizeClassAllocator64<AP64> PrimaryAllocator; 12968d75effSDimitry Andric #elif defined(__aarch64__) 130bdd1243dSDimitry Andric static const uptr kMaxAllowedMallocSize = 8UL << 30; 13168d75effSDimitry Andric 132bdd1243dSDimitry Andric struct AP64 { 133bdd1243dSDimitry Andric static const uptr kSpaceBeg = 0xE00000000000ULL; 134bdd1243dSDimitry Andric static const uptr kSpaceSize = 0x40000000000; // 4T. 13568d75effSDimitry Andric static const uptr kMetadataSize = sizeof(Metadata); 136bdd1243dSDimitry Andric typedef DefaultSizeClassMap SizeClassMap; 13768d75effSDimitry Andric typedef MsanMapUnmapCallback MapUnmapCallback; 13868d75effSDimitry Andric static const uptr kFlags = 0; 139bdd1243dSDimitry Andric using AddressSpaceView = LocalAddressSpaceView; 14068d75effSDimitry Andric }; 141bdd1243dSDimitry Andric typedef SizeClassAllocator64<AP64> PrimaryAllocator; 14268d75effSDimitry Andric #endif 14368d75effSDimitry Andric typedef CombinedAllocator<PrimaryAllocator> Allocator; 14468d75effSDimitry Andric typedef Allocator::AllocatorCache AllocatorCache; 14568d75effSDimitry Andric 14668d75effSDimitry Andric static Allocator allocator; 14768d75effSDimitry Andric static AllocatorCache fallback_allocator_cache; 14868d75effSDimitry Andric static StaticSpinMutex fallback_mutex; 14968d75effSDimitry Andric 150480093f4SDimitry Andric static uptr max_malloc_size; 151480093f4SDimitry Andric 15268d75effSDimitry Andric void MsanAllocatorInit() { 15368d75effSDimitry Andric SetAllocatorMayReturnNull(common_flags()->allocator_may_return_null); 15468d75effSDimitry Andric allocator.Init(common_flags()->allocator_release_to_os_interval_ms); 155480093f4SDimitry Andric if (common_flags()->max_allocation_size_mb) 156480093f4SDimitry Andric max_malloc_size = Min(common_flags()->max_allocation_size_mb << 20, 157480093f4SDimitry Andric kMaxAllowedMallocSize); 158480093f4SDimitry Andric else 159480093f4SDimitry Andric max_malloc_size = kMaxAllowedMallocSize; 16068d75effSDimitry Andric } 16168d75effSDimitry Andric 1625f757f3fSDimitry Andric void LockAllocator() { allocator.ForceLock(); } 1635f757f3fSDimitry Andric 1645f757f3fSDimitry Andric void UnlockAllocator() { allocator.ForceUnlock(); } 1655f757f3fSDimitry Andric 16668d75effSDimitry Andric AllocatorCache *GetAllocatorCache(MsanThreadLocalMallocStorage *ms) { 16768d75effSDimitry Andric CHECK(ms); 16868d75effSDimitry Andric CHECK_LE(sizeof(AllocatorCache), sizeof(ms->allocator_cache)); 16968d75effSDimitry Andric return reinterpret_cast<AllocatorCache *>(ms->allocator_cache); 17068d75effSDimitry Andric } 17168d75effSDimitry Andric 17206c3fb27SDimitry Andric void MsanThreadLocalMallocStorage::Init() { 17306c3fb27SDimitry Andric allocator.InitCache(GetAllocatorCache(this)); 17406c3fb27SDimitry Andric } 17506c3fb27SDimitry Andric 17668d75effSDimitry Andric void MsanThreadLocalMallocStorage::CommitBack() { 17768d75effSDimitry Andric allocator.SwallowCache(GetAllocatorCache(this)); 17806c3fb27SDimitry Andric allocator.DestroyCache(GetAllocatorCache(this)); 17968d75effSDimitry Andric } 18068d75effSDimitry Andric 181*1db9f3b2SDimitry Andric static void *MsanAllocate(BufferedStackTrace *stack, uptr size, uptr alignment, 18268d75effSDimitry Andric bool zeroise) { 183*1db9f3b2SDimitry Andric if (UNLIKELY(size > max_malloc_size)) { 18468d75effSDimitry Andric if (AllocatorMayReturnNull()) { 18568d75effSDimitry Andric Report("WARNING: MemorySanitizer failed to allocate 0x%zx bytes\n", size); 18668d75effSDimitry Andric return nullptr; 18768d75effSDimitry Andric } 188*1db9f3b2SDimitry Andric GET_FATAL_STACK_TRACE_IF_EMPTY(stack); 189480093f4SDimitry Andric ReportAllocationSizeTooBig(size, max_malloc_size, stack); 19068d75effSDimitry Andric } 1910eae32dcSDimitry Andric if (UNLIKELY(IsRssLimitExceeded())) { 1920eae32dcSDimitry Andric if (AllocatorMayReturnNull()) 1930eae32dcSDimitry Andric return nullptr; 194*1db9f3b2SDimitry Andric GET_FATAL_STACK_TRACE_IF_EMPTY(stack); 1950eae32dcSDimitry Andric ReportRssLimitExceeded(stack); 1960eae32dcSDimitry Andric } 19768d75effSDimitry Andric MsanThread *t = GetCurrentThread(); 19868d75effSDimitry Andric void *allocated; 19968d75effSDimitry Andric if (t) { 20068d75effSDimitry Andric AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage()); 20168d75effSDimitry Andric allocated = allocator.Allocate(cache, size, alignment); 20268d75effSDimitry Andric } else { 20368d75effSDimitry Andric SpinMutexLock l(&fallback_mutex); 20468d75effSDimitry Andric AllocatorCache *cache = &fallback_allocator_cache; 20568d75effSDimitry Andric allocated = allocator.Allocate(cache, size, alignment); 20668d75effSDimitry Andric } 20768d75effSDimitry Andric if (UNLIKELY(!allocated)) { 20868d75effSDimitry Andric SetAllocatorOutOfMemory(); 20968d75effSDimitry Andric if (AllocatorMayReturnNull()) 21068d75effSDimitry Andric return nullptr; 211*1db9f3b2SDimitry Andric GET_FATAL_STACK_TRACE_IF_EMPTY(stack); 21268d75effSDimitry Andric ReportOutOfMemory(size, stack); 21368d75effSDimitry Andric } 21468d75effSDimitry Andric Metadata *meta = 21568d75effSDimitry Andric reinterpret_cast<Metadata *>(allocator.GetMetaData(allocated)); 21668d75effSDimitry Andric meta->requested_size = size; 21768d75effSDimitry Andric if (zeroise) { 21806c3fb27SDimitry Andric if (allocator.FromPrimary(allocated)) 21968d75effSDimitry Andric __msan_clear_and_unpoison(allocated, size); 22006c3fb27SDimitry Andric else 22106c3fb27SDimitry Andric __msan_unpoison(allocated, size); // Mem is already zeroed. 22268d75effSDimitry Andric } else if (flags()->poison_in_malloc) { 22368d75effSDimitry Andric __msan_poison(allocated, size); 22468d75effSDimitry Andric if (__msan_get_track_origins()) { 22568d75effSDimitry Andric stack->tag = StackTrace::TAG_ALLOC; 22668d75effSDimitry Andric Origin o = Origin::CreateHeapOrigin(stack); 22768d75effSDimitry Andric __msan_set_origin(allocated, size, o.raw_id()); 22868d75effSDimitry Andric } 22968d75effSDimitry Andric } 23081ad6265SDimitry Andric UnpoisonParam(2); 23181ad6265SDimitry Andric RunMallocHooks(allocated, size); 23268d75effSDimitry Andric return allocated; 23368d75effSDimitry Andric } 23468d75effSDimitry Andric 235*1db9f3b2SDimitry Andric void MsanDeallocate(BufferedStackTrace *stack, void *p) { 23668d75effSDimitry Andric CHECK(p); 23781ad6265SDimitry Andric UnpoisonParam(1); 23881ad6265SDimitry Andric RunFreeHooks(p); 23981ad6265SDimitry Andric 24068d75effSDimitry Andric Metadata *meta = reinterpret_cast<Metadata *>(allocator.GetMetaData(p)); 24168d75effSDimitry Andric uptr size = meta->requested_size; 24268d75effSDimitry Andric meta->requested_size = 0; 24368d75effSDimitry Andric // This memory will not be reused by anyone else, so we are free to keep it 24406c3fb27SDimitry Andric // poisoned. The secondary allocator will unmap and unpoison by 24506c3fb27SDimitry Andric // MsanMapUnmapCallback, no need to poison it here. 24606c3fb27SDimitry Andric if (flags()->poison_in_free && allocator.FromPrimary(p)) { 24768d75effSDimitry Andric __msan_poison(p, size); 24868d75effSDimitry Andric if (__msan_get_track_origins()) { 24968d75effSDimitry Andric stack->tag = StackTrace::TAG_DEALLOC; 25068d75effSDimitry Andric Origin o = Origin::CreateHeapOrigin(stack); 25168d75effSDimitry Andric __msan_set_origin(p, size, o.raw_id()); 25268d75effSDimitry Andric } 25368d75effSDimitry Andric } 25468d75effSDimitry Andric MsanThread *t = GetCurrentThread(); 25568d75effSDimitry Andric if (t) { 25668d75effSDimitry Andric AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage()); 25768d75effSDimitry Andric allocator.Deallocate(cache, p); 25868d75effSDimitry Andric } else { 25968d75effSDimitry Andric SpinMutexLock l(&fallback_mutex); 26068d75effSDimitry Andric AllocatorCache *cache = &fallback_allocator_cache; 26168d75effSDimitry Andric allocator.Deallocate(cache, p); 26268d75effSDimitry Andric } 26368d75effSDimitry Andric } 26468d75effSDimitry Andric 265*1db9f3b2SDimitry Andric static void *MsanReallocate(BufferedStackTrace *stack, void *old_p, 266*1db9f3b2SDimitry Andric uptr new_size, uptr alignment) { 26768d75effSDimitry Andric Metadata *meta = reinterpret_cast<Metadata*>(allocator.GetMetaData(old_p)); 26868d75effSDimitry Andric uptr old_size = meta->requested_size; 26968d75effSDimitry Andric uptr actually_allocated_size = allocator.GetActuallyAllocatedSize(old_p); 27068d75effSDimitry Andric if (new_size <= actually_allocated_size) { 27168d75effSDimitry Andric // We are not reallocating here. 27268d75effSDimitry Andric meta->requested_size = new_size; 27368d75effSDimitry Andric if (new_size > old_size) { 27468d75effSDimitry Andric if (flags()->poison_in_malloc) { 27568d75effSDimitry Andric stack->tag = StackTrace::TAG_ALLOC; 27668d75effSDimitry Andric PoisonMemory((char *)old_p + old_size, new_size - old_size, stack); 27768d75effSDimitry Andric } 27868d75effSDimitry Andric } 27968d75effSDimitry Andric return old_p; 28068d75effSDimitry Andric } 28168d75effSDimitry Andric uptr memcpy_size = Min(new_size, old_size); 28268d75effSDimitry Andric void *new_p = MsanAllocate(stack, new_size, alignment, false /*zeroise*/); 28368d75effSDimitry Andric if (new_p) { 28468d75effSDimitry Andric CopyMemory(new_p, old_p, memcpy_size, stack); 28568d75effSDimitry Andric MsanDeallocate(stack, old_p); 28668d75effSDimitry Andric } 28768d75effSDimitry Andric return new_p; 28868d75effSDimitry Andric } 28968d75effSDimitry Andric 290*1db9f3b2SDimitry Andric static void *MsanCalloc(BufferedStackTrace *stack, uptr nmemb, uptr size) { 29168d75effSDimitry Andric if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) { 29268d75effSDimitry Andric if (AllocatorMayReturnNull()) 29368d75effSDimitry Andric return nullptr; 294*1db9f3b2SDimitry Andric GET_FATAL_STACK_TRACE_IF_EMPTY(stack); 29568d75effSDimitry Andric ReportCallocOverflow(nmemb, size, stack); 29668d75effSDimitry Andric } 29768d75effSDimitry Andric return MsanAllocate(stack, nmemb * size, sizeof(u64), true); 29868d75effSDimitry Andric } 29968d75effSDimitry Andric 30006c3fb27SDimitry Andric static const void *AllocationBegin(const void *p) { 30106c3fb27SDimitry Andric if (!p) 30206c3fb27SDimitry Andric return nullptr; 30306c3fb27SDimitry Andric void *beg = allocator.GetBlockBegin(p); 30406c3fb27SDimitry Andric if (!beg) 30506c3fb27SDimitry Andric return nullptr; 30606c3fb27SDimitry Andric Metadata *b = (Metadata *)allocator.GetMetaData(beg); 30706c3fb27SDimitry Andric if (!b) 30806c3fb27SDimitry Andric return nullptr; 30906c3fb27SDimitry Andric if (b->requested_size == 0) 31006c3fb27SDimitry Andric return nullptr; 31106c3fb27SDimitry Andric 31206c3fb27SDimitry Andric return (const void *)beg; 31306c3fb27SDimitry Andric } 31406c3fb27SDimitry Andric 31568d75effSDimitry Andric static uptr AllocationSize(const void *p) { 31668d75effSDimitry Andric if (!p) return 0; 31768d75effSDimitry Andric const void *beg = allocator.GetBlockBegin(p); 31868d75effSDimitry Andric if (beg != p) return 0; 31968d75effSDimitry Andric Metadata *b = (Metadata *)allocator.GetMetaData(p); 32068d75effSDimitry Andric return b->requested_size; 32168d75effSDimitry Andric } 32268d75effSDimitry Andric 32306c3fb27SDimitry Andric static uptr AllocationSizeFast(const void *p) { 32406c3fb27SDimitry Andric return reinterpret_cast<Metadata *>(allocator.GetMetaData(p))->requested_size; 32506c3fb27SDimitry Andric } 32606c3fb27SDimitry Andric 327*1db9f3b2SDimitry Andric void *msan_malloc(uptr size, BufferedStackTrace *stack) { 32868d75effSDimitry Andric return SetErrnoOnNull(MsanAllocate(stack, size, sizeof(u64), false)); 32968d75effSDimitry Andric } 33068d75effSDimitry Andric 331*1db9f3b2SDimitry Andric void *msan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack) { 33268d75effSDimitry Andric return SetErrnoOnNull(MsanCalloc(stack, nmemb, size)); 33368d75effSDimitry Andric } 33468d75effSDimitry Andric 335*1db9f3b2SDimitry Andric void *msan_realloc(void *ptr, uptr size, BufferedStackTrace *stack) { 33668d75effSDimitry Andric if (!ptr) 33768d75effSDimitry Andric return SetErrnoOnNull(MsanAllocate(stack, size, sizeof(u64), false)); 33868d75effSDimitry Andric if (size == 0) { 33968d75effSDimitry Andric MsanDeallocate(stack, ptr); 34068d75effSDimitry Andric return nullptr; 34168d75effSDimitry Andric } 34268d75effSDimitry Andric return SetErrnoOnNull(MsanReallocate(stack, ptr, size, sizeof(u64))); 34368d75effSDimitry Andric } 34468d75effSDimitry Andric 345*1db9f3b2SDimitry Andric void *msan_reallocarray(void *ptr, uptr nmemb, uptr size, 346*1db9f3b2SDimitry Andric BufferedStackTrace *stack) { 34768d75effSDimitry Andric if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) { 34868d75effSDimitry Andric errno = errno_ENOMEM; 34968d75effSDimitry Andric if (AllocatorMayReturnNull()) 35068d75effSDimitry Andric return nullptr; 351*1db9f3b2SDimitry Andric GET_FATAL_STACK_TRACE_IF_EMPTY(stack); 35268d75effSDimitry Andric ReportReallocArrayOverflow(nmemb, size, stack); 35368d75effSDimitry Andric } 35468d75effSDimitry Andric return msan_realloc(ptr, nmemb * size, stack); 35568d75effSDimitry Andric } 35668d75effSDimitry Andric 357*1db9f3b2SDimitry Andric void *msan_valloc(uptr size, BufferedStackTrace *stack) { 35868d75effSDimitry Andric return SetErrnoOnNull(MsanAllocate(stack, size, GetPageSizeCached(), false)); 35968d75effSDimitry Andric } 36068d75effSDimitry Andric 361*1db9f3b2SDimitry Andric void *msan_pvalloc(uptr size, BufferedStackTrace *stack) { 36268d75effSDimitry Andric uptr PageSize = GetPageSizeCached(); 36368d75effSDimitry Andric if (UNLIKELY(CheckForPvallocOverflow(size, PageSize))) { 36468d75effSDimitry Andric errno = errno_ENOMEM; 36568d75effSDimitry Andric if (AllocatorMayReturnNull()) 36668d75effSDimitry Andric return nullptr; 367*1db9f3b2SDimitry Andric GET_FATAL_STACK_TRACE_IF_EMPTY(stack); 36868d75effSDimitry Andric ReportPvallocOverflow(size, stack); 36968d75effSDimitry Andric } 37068d75effSDimitry Andric // pvalloc(0) should allocate one page. 37168d75effSDimitry Andric size = size ? RoundUpTo(size, PageSize) : PageSize; 37268d75effSDimitry Andric return SetErrnoOnNull(MsanAllocate(stack, size, PageSize, false)); 37368d75effSDimitry Andric } 37468d75effSDimitry Andric 375*1db9f3b2SDimitry Andric void *msan_aligned_alloc(uptr alignment, uptr size, BufferedStackTrace *stack) { 37668d75effSDimitry Andric if (UNLIKELY(!CheckAlignedAllocAlignmentAndSize(alignment, size))) { 37768d75effSDimitry Andric errno = errno_EINVAL; 37868d75effSDimitry Andric if (AllocatorMayReturnNull()) 37968d75effSDimitry Andric return nullptr; 380*1db9f3b2SDimitry Andric GET_FATAL_STACK_TRACE_IF_EMPTY(stack); 38168d75effSDimitry Andric ReportInvalidAlignedAllocAlignment(size, alignment, stack); 38268d75effSDimitry Andric } 38368d75effSDimitry Andric return SetErrnoOnNull(MsanAllocate(stack, size, alignment, false)); 38468d75effSDimitry Andric } 38568d75effSDimitry Andric 386*1db9f3b2SDimitry Andric void *msan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack) { 38768d75effSDimitry Andric if (UNLIKELY(!IsPowerOfTwo(alignment))) { 38868d75effSDimitry Andric errno = errno_EINVAL; 38968d75effSDimitry Andric if (AllocatorMayReturnNull()) 39068d75effSDimitry Andric return nullptr; 391*1db9f3b2SDimitry Andric GET_FATAL_STACK_TRACE_IF_EMPTY(stack); 39268d75effSDimitry Andric ReportInvalidAllocationAlignment(alignment, stack); 39368d75effSDimitry Andric } 39468d75effSDimitry Andric return SetErrnoOnNull(MsanAllocate(stack, size, alignment, false)); 39568d75effSDimitry Andric } 39668d75effSDimitry Andric 39768d75effSDimitry Andric int msan_posix_memalign(void **memptr, uptr alignment, uptr size, 398*1db9f3b2SDimitry Andric BufferedStackTrace *stack) { 39968d75effSDimitry Andric if (UNLIKELY(!CheckPosixMemalignAlignment(alignment))) { 40068d75effSDimitry Andric if (AllocatorMayReturnNull()) 40168d75effSDimitry Andric return errno_EINVAL; 402*1db9f3b2SDimitry Andric GET_FATAL_STACK_TRACE_IF_EMPTY(stack); 40368d75effSDimitry Andric ReportInvalidPosixMemalignAlignment(alignment, stack); 40468d75effSDimitry Andric } 40568d75effSDimitry Andric void *ptr = MsanAllocate(stack, size, alignment, false); 40668d75effSDimitry Andric if (UNLIKELY(!ptr)) 40768d75effSDimitry Andric // OOM error is already taken care of by MsanAllocate. 40868d75effSDimitry Andric return errno_ENOMEM; 40968d75effSDimitry Andric CHECK(IsAligned((uptr)ptr, alignment)); 41068d75effSDimitry Andric *memptr = ptr; 41168d75effSDimitry Andric return 0; 41268d75effSDimitry Andric } 41368d75effSDimitry Andric 41468d75effSDimitry Andric } // namespace __msan 41568d75effSDimitry Andric 41668d75effSDimitry Andric using namespace __msan; 41768d75effSDimitry Andric 41868d75effSDimitry Andric uptr __sanitizer_get_current_allocated_bytes() { 41968d75effSDimitry Andric uptr stats[AllocatorStatCount]; 42068d75effSDimitry Andric allocator.GetStats(stats); 42168d75effSDimitry Andric return stats[AllocatorStatAllocated]; 42268d75effSDimitry Andric } 42368d75effSDimitry Andric 42468d75effSDimitry Andric uptr __sanitizer_get_heap_size() { 42568d75effSDimitry Andric uptr stats[AllocatorStatCount]; 42668d75effSDimitry Andric allocator.GetStats(stats); 42768d75effSDimitry Andric return stats[AllocatorStatMapped]; 42868d75effSDimitry Andric } 42968d75effSDimitry Andric 43068d75effSDimitry Andric uptr __sanitizer_get_free_bytes() { return 1; } 43168d75effSDimitry Andric 43268d75effSDimitry Andric uptr __sanitizer_get_unmapped_bytes() { return 1; } 43368d75effSDimitry Andric 43468d75effSDimitry Andric uptr __sanitizer_get_estimated_allocated_size(uptr size) { return size; } 43568d75effSDimitry Andric 43668d75effSDimitry Andric int __sanitizer_get_ownership(const void *p) { return AllocationSize(p) != 0; } 43768d75effSDimitry Andric 43806c3fb27SDimitry Andric const void *__sanitizer_get_allocated_begin(const void *p) { 43906c3fb27SDimitry Andric return AllocationBegin(p); 44006c3fb27SDimitry Andric } 44106c3fb27SDimitry Andric 44268d75effSDimitry Andric uptr __sanitizer_get_allocated_size(const void *p) { return AllocationSize(p); } 44306c3fb27SDimitry Andric 44406c3fb27SDimitry Andric uptr __sanitizer_get_allocated_size_fast(const void *p) { 44506c3fb27SDimitry Andric DCHECK_EQ(p, __sanitizer_get_allocated_begin(p)); 44606c3fb27SDimitry Andric uptr ret = AllocationSizeFast(p); 44706c3fb27SDimitry Andric DCHECK_EQ(ret, __sanitizer_get_allocated_size(p)); 44806c3fb27SDimitry Andric return ret; 44906c3fb27SDimitry Andric } 45006c3fb27SDimitry Andric 45106c3fb27SDimitry Andric void __sanitizer_purge_allocator() { allocator.ForceReleaseToOS(); } 452