[compiler-rt] [scudo] Split the code paths which enable memory tagging (PR #83493)
Mitch Phillips via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 2 03:59:28 PDT 2024
================
@@ -401,133 +401,18 @@ class Allocator {
reportOutOfMemory(NeededSize);
}
- const uptr BlockUptr = reinterpret_cast<uptr>(Block);
- const uptr UnalignedUserPtr = BlockUptr + Chunk::getHeaderSize();
- const uptr UserPtr = roundUp(UnalignedUserPtr, Alignment);
-
- void *Ptr = reinterpret_cast<void *>(UserPtr);
- void *TaggedPtr = Ptr;
- if (LIKELY(ClassId)) {
- // We only need to zero or tag the contents for Primary backed
- // allocations. We only set tags for primary allocations in order to avoid
- // faulting potentially large numbers of pages for large secondary
- // allocations. We assume that guard pages are enough to protect these
- // allocations.
- //
- // FIXME: When the kernel provides a way to set the background tag of a
- // mapping, we should be able to tag secondary allocations as well.
- //
- // When memory tagging is enabled, zeroing the contents is done as part of
- // setting the tag.
- if (UNLIKELY(useMemoryTagging<Config>(Options))) {
- uptr PrevUserPtr;
- Chunk::UnpackedHeader Header;
- const uptr BlockSize = PrimaryT::getSizeByClassId(ClassId);
- const uptr BlockEnd = BlockUptr + BlockSize;
- // If possible, try to reuse the UAF tag that was set by deallocate().
- // For simplicity, only reuse tags if we have the same start address as
- // the previous allocation. This handles the majority of cases since
- // most allocations will not be more aligned than the minimum alignment.
- //
- // We need to handle situations involving reclaimed chunks, and retag
- // the reclaimed portions if necessary. In the case where the chunk is
- // fully reclaimed, the chunk's header will be zero, which will trigger
- // the code path for new mappings and invalid chunks that prepares the
- // chunk from scratch. There are three possibilities for partial
- // reclaiming:
- //
- // (1) Header was reclaimed, data was partially reclaimed.
- // (2) Header was not reclaimed, all data was reclaimed (e.g. because
- // data started on a page boundary).
- // (3) Header was not reclaimed, data was partially reclaimed.
- //
- // Case (1) will be handled in the same way as for full reclaiming,
- // since the header will be zero.
- //
- // We can detect case (2) by loading the tag from the start
- // of the chunk. If it is zero, it means that either all data was
- // reclaimed (since we never use zero as the chunk tag), or that the
- // previous allocation was of size zero. Either way, we need to prepare
- // a new chunk from scratch.
- //
- // We can detect case (3) by moving to the next page (if covered by the
- // chunk) and loading the tag of its first granule. If it is zero, it
- // means that all following pages may need to be retagged. On the other
- // hand, if it is nonzero, we can assume that all following pages are
- // still tagged, according to the logic that if any of the pages
- // following the next page were reclaimed, the next page would have been
- // reclaimed as well.
- uptr TaggedUserPtr;
- if (getChunkFromBlock(BlockUptr, &PrevUserPtr, &Header) &&
- PrevUserPtr == UserPtr &&
- (TaggedUserPtr = loadTag(UserPtr)) != UserPtr) {
- uptr PrevEnd = TaggedUserPtr + Header.SizeOrUnusedBytes;
- const uptr NextPage = roundUp(TaggedUserPtr, getPageSizeCached());
- if (NextPage < PrevEnd && loadTag(NextPage) != NextPage)
- PrevEnd = NextPage;
- TaggedPtr = reinterpret_cast<void *>(TaggedUserPtr);
- resizeTaggedChunk(PrevEnd, TaggedUserPtr + Size, Size, BlockEnd);
- if (UNLIKELY(FillContents != NoFill && !Header.OriginOrWasZeroed)) {
- // If an allocation needs to be zeroed (i.e. calloc) we can normally
- // avoid zeroing the memory now since we can rely on memory having
- // been zeroed on free, as this is normally done while setting the
- // UAF tag. But if tagging was disabled per-thread when the memory
- // was freed, it would not have been retagged and thus zeroed, and
- // therefore it needs to be zeroed now.
- memset(TaggedPtr, 0,
- Min(Size, roundUp(PrevEnd - TaggedUserPtr,
- archMemoryTagGranuleSize())));
- } else if (Size) {
- // Clear any stack metadata that may have previously been stored in
- // the chunk data.
- memset(TaggedPtr, 0, archMemoryTagGranuleSize());
- }
- } else {
- const uptr OddEvenMask =
- computeOddEvenMaskForPointerMaybe(Options, BlockUptr, ClassId);
- TaggedPtr = prepareTaggedChunk(Ptr, Size, OddEvenMask, BlockEnd);
- }
- storePrimaryAllocationStackMaybe(Options, Ptr);
- } else {
- Block = addHeaderTag(Block);
- Ptr = addHeaderTag(Ptr);
- if (UNLIKELY(FillContents != NoFill)) {
- // This condition is not necessarily unlikely, but since memset is
- // costly, we might as well mark it as such.
- memset(Block, FillContents == ZeroFill ? 0 : PatternFillByte,
- PrimaryT::getSizeByClassId(ClassId));
- }
- }
+ const uptr UserPtr = roundUp(
+ reinterpret_cast<uptr>(Block) + Chunk::getHeaderSize(), Alignment);
+ const uptr SizeOrUnusedBytes =
+ ClassId ? Size : SecondaryBlockEnd - (UserPtr + Size);
+
+ if (LIKELY(!useMemoryTagging<Config>(Options))) {
+ return initChunk(ClassId, Origin, Block, UserPtr, SizeOrUnusedBytes,
+ FillContents);
} else {
- Block = addHeaderTag(Block);
- Ptr = addHeaderTag(Ptr);
- if (UNLIKELY(useMemoryTagging<Config>(Options))) {
- storeTags(reinterpret_cast<uptr>(Block), reinterpret_cast<uptr>(Ptr));
- storeSecondaryAllocationStackMaybe(Options, Ptr, Size);
- }
+ return initChunkWithMemoryTagging(ClassId, Origin, Block, UserPtr, Size,
----------------
hctim wrote:
Dangling `else` statement after `return`. Remove the `else {` block?
https://github.com/llvm/llvm-project/pull/83493
More information about the llvm-commits
mailing list