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 162*5f757f3fSDimitry Andric void LockAllocator() { allocator.ForceLock(); } 163*5f757f3fSDimitry Andric 164*5f757f3fSDimitry Andric void UnlockAllocator() { allocator.ForceUnlock(); } 165*5f757f3fSDimitry 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 18168d75effSDimitry Andric static void *MsanAllocate(StackTrace *stack, uptr size, uptr alignment, 18268d75effSDimitry Andric bool zeroise) { 183480093f4SDimitry Andric if (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 } 188480093f4SDimitry Andric ReportAllocationSizeTooBig(size, max_malloc_size, stack); 18968d75effSDimitry Andric } 1900eae32dcSDimitry Andric if (UNLIKELY(IsRssLimitExceeded())) { 1910eae32dcSDimitry Andric if (AllocatorMayReturnNull()) 1920eae32dcSDimitry Andric return nullptr; 1930eae32dcSDimitry Andric ReportRssLimitExceeded(stack); 1940eae32dcSDimitry Andric } 19568d75effSDimitry Andric MsanThread *t = GetCurrentThread(); 19668d75effSDimitry Andric void *allocated; 19768d75effSDimitry Andric if (t) { 19868d75effSDimitry Andric AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage()); 19968d75effSDimitry Andric allocated = allocator.Allocate(cache, size, alignment); 20068d75effSDimitry Andric } else { 20168d75effSDimitry Andric SpinMutexLock l(&fallback_mutex); 20268d75effSDimitry Andric AllocatorCache *cache = &fallback_allocator_cache; 20368d75effSDimitry Andric allocated = allocator.Allocate(cache, size, alignment); 20468d75effSDimitry Andric } 20568d75effSDimitry Andric if (UNLIKELY(!allocated)) { 20668d75effSDimitry Andric SetAllocatorOutOfMemory(); 20768d75effSDimitry Andric if (AllocatorMayReturnNull()) 20868d75effSDimitry Andric return nullptr; 20968d75effSDimitry Andric ReportOutOfMemory(size, stack); 21068d75effSDimitry Andric } 21168d75effSDimitry Andric Metadata *meta = 21268d75effSDimitry Andric reinterpret_cast<Metadata *>(allocator.GetMetaData(allocated)); 21368d75effSDimitry Andric meta->requested_size = size; 21468d75effSDimitry Andric if (zeroise) { 21506c3fb27SDimitry Andric if (allocator.FromPrimary(allocated)) 21668d75effSDimitry Andric __msan_clear_and_unpoison(allocated, size); 21706c3fb27SDimitry Andric else 21806c3fb27SDimitry Andric __msan_unpoison(allocated, size); // Mem is already zeroed. 21968d75effSDimitry Andric } else if (flags()->poison_in_malloc) { 22068d75effSDimitry Andric __msan_poison(allocated, size); 22168d75effSDimitry Andric if (__msan_get_track_origins()) { 22268d75effSDimitry Andric stack->tag = StackTrace::TAG_ALLOC; 22368d75effSDimitry Andric Origin o = Origin::CreateHeapOrigin(stack); 22468d75effSDimitry Andric __msan_set_origin(allocated, size, o.raw_id()); 22568d75effSDimitry Andric } 22668d75effSDimitry Andric } 22781ad6265SDimitry Andric UnpoisonParam(2); 22881ad6265SDimitry Andric RunMallocHooks(allocated, size); 22968d75effSDimitry Andric return allocated; 23068d75effSDimitry Andric } 23168d75effSDimitry Andric 23268d75effSDimitry Andric void MsanDeallocate(StackTrace *stack, void *p) { 23368d75effSDimitry Andric CHECK(p); 23481ad6265SDimitry Andric UnpoisonParam(1); 23581ad6265SDimitry Andric RunFreeHooks(p); 23681ad6265SDimitry Andric 23768d75effSDimitry Andric Metadata *meta = reinterpret_cast<Metadata *>(allocator.GetMetaData(p)); 23868d75effSDimitry Andric uptr size = meta->requested_size; 23968d75effSDimitry Andric meta->requested_size = 0; 24068d75effSDimitry Andric // This memory will not be reused by anyone else, so we are free to keep it 24106c3fb27SDimitry Andric // poisoned. The secondary allocator will unmap and unpoison by 24206c3fb27SDimitry Andric // MsanMapUnmapCallback, no need to poison it here. 24306c3fb27SDimitry Andric if (flags()->poison_in_free && allocator.FromPrimary(p)) { 24468d75effSDimitry Andric __msan_poison(p, size); 24568d75effSDimitry Andric if (__msan_get_track_origins()) { 24668d75effSDimitry Andric stack->tag = StackTrace::TAG_DEALLOC; 24768d75effSDimitry Andric Origin o = Origin::CreateHeapOrigin(stack); 24868d75effSDimitry Andric __msan_set_origin(p, size, o.raw_id()); 24968d75effSDimitry Andric } 25068d75effSDimitry Andric } 25168d75effSDimitry Andric MsanThread *t = GetCurrentThread(); 25268d75effSDimitry Andric if (t) { 25368d75effSDimitry Andric AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage()); 25468d75effSDimitry Andric allocator.Deallocate(cache, p); 25568d75effSDimitry Andric } else { 25668d75effSDimitry Andric SpinMutexLock l(&fallback_mutex); 25768d75effSDimitry Andric AllocatorCache *cache = &fallback_allocator_cache; 25868d75effSDimitry Andric allocator.Deallocate(cache, p); 25968d75effSDimitry Andric } 26068d75effSDimitry Andric } 26168d75effSDimitry Andric 262fe6060f1SDimitry Andric static void *MsanReallocate(StackTrace *stack, void *old_p, uptr new_size, 26368d75effSDimitry Andric uptr alignment) { 26468d75effSDimitry Andric Metadata *meta = reinterpret_cast<Metadata*>(allocator.GetMetaData(old_p)); 26568d75effSDimitry Andric uptr old_size = meta->requested_size; 26668d75effSDimitry Andric uptr actually_allocated_size = allocator.GetActuallyAllocatedSize(old_p); 26768d75effSDimitry Andric if (new_size <= actually_allocated_size) { 26868d75effSDimitry Andric // We are not reallocating here. 26968d75effSDimitry Andric meta->requested_size = new_size; 27068d75effSDimitry Andric if (new_size > old_size) { 27168d75effSDimitry Andric if (flags()->poison_in_malloc) { 27268d75effSDimitry Andric stack->tag = StackTrace::TAG_ALLOC; 27368d75effSDimitry Andric PoisonMemory((char *)old_p + old_size, new_size - old_size, stack); 27468d75effSDimitry Andric } 27568d75effSDimitry Andric } 27668d75effSDimitry Andric return old_p; 27768d75effSDimitry Andric } 27868d75effSDimitry Andric uptr memcpy_size = Min(new_size, old_size); 27968d75effSDimitry Andric void *new_p = MsanAllocate(stack, new_size, alignment, false /*zeroise*/); 28068d75effSDimitry Andric if (new_p) { 28168d75effSDimitry Andric CopyMemory(new_p, old_p, memcpy_size, stack); 28268d75effSDimitry Andric MsanDeallocate(stack, old_p); 28368d75effSDimitry Andric } 28468d75effSDimitry Andric return new_p; 28568d75effSDimitry Andric } 28668d75effSDimitry Andric 287fe6060f1SDimitry Andric static void *MsanCalloc(StackTrace *stack, uptr nmemb, uptr size) { 28868d75effSDimitry Andric if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) { 28968d75effSDimitry Andric if (AllocatorMayReturnNull()) 29068d75effSDimitry Andric return nullptr; 29168d75effSDimitry Andric ReportCallocOverflow(nmemb, size, stack); 29268d75effSDimitry Andric } 29368d75effSDimitry Andric return MsanAllocate(stack, nmemb * size, sizeof(u64), true); 29468d75effSDimitry Andric } 29568d75effSDimitry Andric 29606c3fb27SDimitry Andric static const void *AllocationBegin(const void *p) { 29706c3fb27SDimitry Andric if (!p) 29806c3fb27SDimitry Andric return nullptr; 29906c3fb27SDimitry Andric void *beg = allocator.GetBlockBegin(p); 30006c3fb27SDimitry Andric if (!beg) 30106c3fb27SDimitry Andric return nullptr; 30206c3fb27SDimitry Andric Metadata *b = (Metadata *)allocator.GetMetaData(beg); 30306c3fb27SDimitry Andric if (!b) 30406c3fb27SDimitry Andric return nullptr; 30506c3fb27SDimitry Andric if (b->requested_size == 0) 30606c3fb27SDimitry Andric return nullptr; 30706c3fb27SDimitry Andric 30806c3fb27SDimitry Andric return (const void *)beg; 30906c3fb27SDimitry Andric } 31006c3fb27SDimitry Andric 31168d75effSDimitry Andric static uptr AllocationSize(const void *p) { 31268d75effSDimitry Andric if (!p) return 0; 31368d75effSDimitry Andric const void *beg = allocator.GetBlockBegin(p); 31468d75effSDimitry Andric if (beg != p) return 0; 31568d75effSDimitry Andric Metadata *b = (Metadata *)allocator.GetMetaData(p); 31668d75effSDimitry Andric return b->requested_size; 31768d75effSDimitry Andric } 31868d75effSDimitry Andric 31906c3fb27SDimitry Andric static uptr AllocationSizeFast(const void *p) { 32006c3fb27SDimitry Andric return reinterpret_cast<Metadata *>(allocator.GetMetaData(p))->requested_size; 32106c3fb27SDimitry Andric } 32206c3fb27SDimitry Andric 32368d75effSDimitry Andric void *msan_malloc(uptr size, StackTrace *stack) { 32468d75effSDimitry Andric return SetErrnoOnNull(MsanAllocate(stack, size, sizeof(u64), false)); 32568d75effSDimitry Andric } 32668d75effSDimitry Andric 32768d75effSDimitry Andric void *msan_calloc(uptr nmemb, uptr size, StackTrace *stack) { 32868d75effSDimitry Andric return SetErrnoOnNull(MsanCalloc(stack, nmemb, size)); 32968d75effSDimitry Andric } 33068d75effSDimitry Andric 33168d75effSDimitry Andric void *msan_realloc(void *ptr, uptr size, StackTrace *stack) { 33268d75effSDimitry Andric if (!ptr) 33368d75effSDimitry Andric return SetErrnoOnNull(MsanAllocate(stack, size, sizeof(u64), false)); 33468d75effSDimitry Andric if (size == 0) { 33568d75effSDimitry Andric MsanDeallocate(stack, ptr); 33668d75effSDimitry Andric return nullptr; 33768d75effSDimitry Andric } 33868d75effSDimitry Andric return SetErrnoOnNull(MsanReallocate(stack, ptr, size, sizeof(u64))); 33968d75effSDimitry Andric } 34068d75effSDimitry Andric 34168d75effSDimitry Andric void *msan_reallocarray(void *ptr, uptr nmemb, uptr size, StackTrace *stack) { 34268d75effSDimitry Andric if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) { 34368d75effSDimitry Andric errno = errno_ENOMEM; 34468d75effSDimitry Andric if (AllocatorMayReturnNull()) 34568d75effSDimitry Andric return nullptr; 34668d75effSDimitry Andric ReportReallocArrayOverflow(nmemb, size, stack); 34768d75effSDimitry Andric } 34868d75effSDimitry Andric return msan_realloc(ptr, nmemb * size, stack); 34968d75effSDimitry Andric } 35068d75effSDimitry Andric 35168d75effSDimitry Andric void *msan_valloc(uptr size, StackTrace *stack) { 35268d75effSDimitry Andric return SetErrnoOnNull(MsanAllocate(stack, size, GetPageSizeCached(), false)); 35368d75effSDimitry Andric } 35468d75effSDimitry Andric 35568d75effSDimitry Andric void *msan_pvalloc(uptr size, StackTrace *stack) { 35668d75effSDimitry Andric uptr PageSize = GetPageSizeCached(); 35768d75effSDimitry Andric if (UNLIKELY(CheckForPvallocOverflow(size, PageSize))) { 35868d75effSDimitry Andric errno = errno_ENOMEM; 35968d75effSDimitry Andric if (AllocatorMayReturnNull()) 36068d75effSDimitry Andric return nullptr; 36168d75effSDimitry Andric ReportPvallocOverflow(size, stack); 36268d75effSDimitry Andric } 36368d75effSDimitry Andric // pvalloc(0) should allocate one page. 36468d75effSDimitry Andric size = size ? RoundUpTo(size, PageSize) : PageSize; 36568d75effSDimitry Andric return SetErrnoOnNull(MsanAllocate(stack, size, PageSize, false)); 36668d75effSDimitry Andric } 36768d75effSDimitry Andric 36868d75effSDimitry Andric void *msan_aligned_alloc(uptr alignment, uptr size, StackTrace *stack) { 36968d75effSDimitry Andric if (UNLIKELY(!CheckAlignedAllocAlignmentAndSize(alignment, size))) { 37068d75effSDimitry Andric errno = errno_EINVAL; 37168d75effSDimitry Andric if (AllocatorMayReturnNull()) 37268d75effSDimitry Andric return nullptr; 37368d75effSDimitry Andric ReportInvalidAlignedAllocAlignment(size, alignment, stack); 37468d75effSDimitry Andric } 37568d75effSDimitry Andric return SetErrnoOnNull(MsanAllocate(stack, size, alignment, false)); 37668d75effSDimitry Andric } 37768d75effSDimitry Andric 37868d75effSDimitry Andric void *msan_memalign(uptr alignment, uptr size, StackTrace *stack) { 37968d75effSDimitry Andric if (UNLIKELY(!IsPowerOfTwo(alignment))) { 38068d75effSDimitry Andric errno = errno_EINVAL; 38168d75effSDimitry Andric if (AllocatorMayReturnNull()) 38268d75effSDimitry Andric return nullptr; 38368d75effSDimitry Andric ReportInvalidAllocationAlignment(alignment, stack); 38468d75effSDimitry Andric } 38568d75effSDimitry Andric return SetErrnoOnNull(MsanAllocate(stack, size, alignment, false)); 38668d75effSDimitry Andric } 38768d75effSDimitry Andric 38868d75effSDimitry Andric int msan_posix_memalign(void **memptr, uptr alignment, uptr size, 38968d75effSDimitry Andric StackTrace *stack) { 39068d75effSDimitry Andric if (UNLIKELY(!CheckPosixMemalignAlignment(alignment))) { 39168d75effSDimitry Andric if (AllocatorMayReturnNull()) 39268d75effSDimitry Andric return errno_EINVAL; 39368d75effSDimitry Andric ReportInvalidPosixMemalignAlignment(alignment, stack); 39468d75effSDimitry Andric } 39568d75effSDimitry Andric void *ptr = MsanAllocate(stack, size, alignment, false); 39668d75effSDimitry Andric if (UNLIKELY(!ptr)) 39768d75effSDimitry Andric // OOM error is already taken care of by MsanAllocate. 39868d75effSDimitry Andric return errno_ENOMEM; 39968d75effSDimitry Andric CHECK(IsAligned((uptr)ptr, alignment)); 40068d75effSDimitry Andric *memptr = ptr; 40168d75effSDimitry Andric return 0; 40268d75effSDimitry Andric } 40368d75effSDimitry Andric 40468d75effSDimitry Andric } // namespace __msan 40568d75effSDimitry Andric 40668d75effSDimitry Andric using namespace __msan; 40768d75effSDimitry Andric 40868d75effSDimitry Andric uptr __sanitizer_get_current_allocated_bytes() { 40968d75effSDimitry Andric uptr stats[AllocatorStatCount]; 41068d75effSDimitry Andric allocator.GetStats(stats); 41168d75effSDimitry Andric return stats[AllocatorStatAllocated]; 41268d75effSDimitry Andric } 41368d75effSDimitry Andric 41468d75effSDimitry Andric uptr __sanitizer_get_heap_size() { 41568d75effSDimitry Andric uptr stats[AllocatorStatCount]; 41668d75effSDimitry Andric allocator.GetStats(stats); 41768d75effSDimitry Andric return stats[AllocatorStatMapped]; 41868d75effSDimitry Andric } 41968d75effSDimitry Andric 42068d75effSDimitry Andric uptr __sanitizer_get_free_bytes() { return 1; } 42168d75effSDimitry Andric 42268d75effSDimitry Andric uptr __sanitizer_get_unmapped_bytes() { return 1; } 42368d75effSDimitry Andric 42468d75effSDimitry Andric uptr __sanitizer_get_estimated_allocated_size(uptr size) { return size; } 42568d75effSDimitry Andric 42668d75effSDimitry Andric int __sanitizer_get_ownership(const void *p) { return AllocationSize(p) != 0; } 42768d75effSDimitry Andric 42806c3fb27SDimitry Andric const void *__sanitizer_get_allocated_begin(const void *p) { 42906c3fb27SDimitry Andric return AllocationBegin(p); 43006c3fb27SDimitry Andric } 43106c3fb27SDimitry Andric 43268d75effSDimitry Andric uptr __sanitizer_get_allocated_size(const void *p) { return AllocationSize(p); } 43306c3fb27SDimitry Andric 43406c3fb27SDimitry Andric uptr __sanitizer_get_allocated_size_fast(const void *p) { 43506c3fb27SDimitry Andric DCHECK_EQ(p, __sanitizer_get_allocated_begin(p)); 43606c3fb27SDimitry Andric uptr ret = AllocationSizeFast(p); 43706c3fb27SDimitry Andric DCHECK_EQ(ret, __sanitizer_get_allocated_size(p)); 43806c3fb27SDimitry Andric return ret; 43906c3fb27SDimitry Andric } 44006c3fb27SDimitry Andric 44106c3fb27SDimitry Andric void __sanitizer_purge_allocator() { allocator.ForceReleaseToOS(); } 442