Skip to content

Commit 1dd5469

Browse files
committed
[scudo] Detect double free when running with MTE.
Try to trigger an MTE fault on double/invalid free by touching the first byte of the allocation with the provided pointer. Differential Revision: https://reviews.llvm.org/D137352
1 parent 87debda commit 1dd5469

File tree

2 files changed

+30
-0
lines changed

2 files changed

+30
-0
lines changed

compiler-rt/lib/scudo/standalone/combined.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,16 @@ class Allocator {
560560
}
561561
}
562562

563+
// Try to detect deallocation with a wrong MTE tag by touching the first
564+
// byte with a correctly tagged pointer. Skip zero-sized allocations that do
565+
// not always store the correct tag value anywhere (for example, a zero
566+
// size, 32 byte aligned allocation in a 32-byte size class will end up with
567+
// header at offset 16 in the block, payload at offset 32, and no space to
568+
// store the tag).
563569
const uptr Size = getSize(Ptr, &Header);
570+
if (useMemoryTagging<Params>(Options) && Size != 0)
571+
*reinterpret_cast<volatile char *>(TaggedPtr);
572+
564573
if (DeleteSize && Options.get(OptionBit::DeleteSizeMismatch)) {
565574
if (UNLIKELY(DeleteSize != Size))
566575
reportDeleteSizeMismatch(Ptr, DeleteSize, Size);

compiler-rt/lib/scudo/standalone/tests/combined_test.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,27 @@ SCUDO_TYPED_TEST(ScudoCombinedDeathTest, UseAfterFree) {
395395
}
396396
}
397397

398+
SCUDO_TYPED_TEST(ScudoCombinedDeathTest, FreeWithTagMismatch) {
399+
auto *Allocator = this->Allocator.get();
400+
401+
if (!Allocator->useMemoryTaggingTestOnly())
402+
return;
403+
404+
// Check that double free is detected.
405+
for (scudo::uptr SizeLog = 0U; SizeLog <= 20U; SizeLog++) {
406+
const scudo::uptr Size = 1U << SizeLog;
407+
EXPECT_DEATH(
408+
{
409+
disableDebuggerdMaybe();
410+
void *P = Allocator->allocate(Size, Origin);
411+
scudo::uptr NewTag = (scudo::extractTag(reinterpret_cast<scudo::uptr>(P)) + 1) % 16;
412+
void *Q = scudo::addFixedTag(scudo::untagPointer(P), NewTag);
413+
Allocator->deallocate(Q, Origin);
414+
},
415+
"");
416+
}
417+
}
418+
398419
SCUDO_TYPED_TEST(ScudoCombinedDeathTest, DisableMemoryTagging) {
399420
auto *Allocator = this->Allocator.get();
400421

0 commit comments

Comments
 (0)