// Allocates a chunk. void *allocate(uptr Size, uptr Alignment, AllocType Type) { if (UNLIKELY(!ThreadInited)) initThread(); if (!IsPowerOfTwo(Alignment)) { dieWithMessage("ERROR: malloc alignment is not a power of 2\n"); } if (Alignment > MaxAlignment) return BackendAllocator.ReturnNullOrDie(); if (Alignment < MinAlignment) Alignment = MinAlignment; if (Size == 0) Size = 1; if (Size >= MaxAllowedMallocSize) return BackendAllocator.ReturnNullOrDie(); uptr RoundedSize = RoundUpTo(Size, MinAlignment); uptr ExtraBytes = ChunkHeaderSize; if (Alignment > MinAlignment) ExtraBytes += Alignment; uptr NeededSize = RoundedSize + ExtraBytes; if (NeededSize >= MaxAllowedMallocSize) return BackendAllocator.ReturnNullOrDie(); void *Ptr; if (LIKELY(!ThreadTornDown)) { Ptr = BackendAllocator.Allocate(&Cache, NeededSize, MinAlignment); } else { SpinMutexLock l(&FallbackMutex); Ptr = BackendAllocator.Allocate(&FallbackAllocatorCache, NeededSize, MinAlignment); } if (!Ptr) return BackendAllocator.ReturnNullOrDie(); // If requested, we will zero out the entire contents of the returned chunk. if (ZeroContents && BackendAllocator.FromPrimary(Ptr)) memset(Ptr, 0, BackendAllocator.GetActuallyAllocatedSize(Ptr)); uptr AllocBeg = reinterpret_cast<uptr>(Ptr); uptr ChunkBeg = AllocBeg + ChunkHeaderSize; if (!IsAligned(ChunkBeg, Alignment)) ChunkBeg = RoundUpTo(ChunkBeg, Alignment); CHECK_LE(ChunkBeg + Size, AllocBeg + NeededSize); ScudoChunk *Chunk = reinterpret_cast<ScudoChunk *>(ChunkBeg - ChunkHeaderSize); UnpackedHeader Header = {}; Header.State = ChunkAllocated; Header.Offset = (ChunkBeg - ChunkHeaderSize - AllocBeg) >> MinAlignmentLog; Header.AllocType = Type; Header.RequestedSize = Size; Header.Salt = static_cast<u16>(Prng.Next()); Chunk->storeHeader(&Header); void *UserPtr = reinterpret_cast<void *>(ChunkBeg); // TODO(kostyak): hooks sound like a terrible idea security wise but might // be needed for things to work properly? // if (&__sanitizer_malloc_hook) __sanitizer_malloc_hook(UserPtr, Size); return UserPtr; }
void *hwasan_pvalloc(uptr size, StackTrace *stack) { uptr PageSize = GetPageSizeCached(); if (UNLIKELY(CheckForPvallocOverflow(size, PageSize))) { errno = errno_ENOMEM; if (AllocatorMayReturnNull()) return nullptr; ReportPvallocOverflow(size, stack); } // pvalloc(0) should allocate one page. size = size ? RoundUpTo(size, PageSize) : PageSize; return SetErrnoOnNull(HwasanAllocate(stack, size, PageSize, false)); }
static uptr TaggedSize(uptr size) { if (!size) size = 1; uptr new_size = RoundUpTo(size, kShadowAlignment); CHECK_GE(new_size, size); return new_size; }