From 584fd96e9eebba95e8335e137c959bae873dbf2b Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Wed, 20 Nov 2013 12:51:14 +0000 Subject: [PATCH] [msan] Unpoison memory that is returned to the OS and flush its shadow. llvm-svn: 195244 --- compiler-rt/lib/msan/msan_allocator.cc | 18 ++++++++++++++++-- compiler-rt/lib/msan/tests/msan_test.cc | 23 +++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/compiler-rt/lib/msan/msan_allocator.cc b/compiler-rt/lib/msan/msan_allocator.cc index 2badf712188b..3c74142bcb16 100644 --- a/compiler-rt/lib/msan/msan_allocator.cc +++ b/compiler-rt/lib/msan/msan_allocator.cc @@ -22,15 +22,29 @@ struct Metadata { uptr requested_size; }; +struct MsanMapUnmapCallback { + void OnMap(uptr p, uptr size) const {} + void OnUnmap(uptr p, uptr size) const { + __msan_unpoison((void *)p, size); + + // We are about to unmap a chunk of user memory. + // Mark the corresponding shadow memory as not needed. + FlushUnneededShadowMemory(MEM_TO_SHADOW(p), size); + if (__msan_get_track_origins()) + FlushUnneededShadowMemory(MEM_TO_ORIGIN(p), size); + } +}; + static const uptr kAllocatorSpace = 0x600000000000ULL; static const uptr kAllocatorSize = 0x80000000000; // 8T. static const uptr kMetadataSize = sizeof(Metadata); static const uptr kMaxAllowedMallocSize = 8UL << 30; typedef SizeClassAllocator64 PrimaryAllocator; + DefaultSizeClassMap, + MsanMapUnmapCallback> PrimaryAllocator; typedef SizeClassAllocatorLocalCache AllocatorCache; -typedef LargeMmapAllocator<> SecondaryAllocator; +typedef LargeMmapAllocator SecondaryAllocator; typedef CombinedAllocator Allocator; diff --git a/compiler-rt/lib/msan/tests/msan_test.cc b/compiler-rt/lib/msan/tests/msan_test.cc index e555fec0beff..a60a232110ed 100644 --- a/compiler-rt/lib/msan/tests/msan_test.cc +++ b/compiler-rt/lib/msan/tests/msan_test.cc @@ -3571,3 +3571,26 @@ TEST(MemorySanitizer, MlockTest) { EXPECT_EQ(0, munlockall()); EXPECT_EQ(0, munlock((void*)0x987, 0x654)); } + +// Test that LargeAllocator unpoisons memory before releasing it to the OS. +TEST(MemorySanitizer, LargeAllocatorUnpoisonsOnFree) { + void *p = malloc(1024 * 1024); + free(p); + + typedef void *(*mmap_fn)(void *, size_t, int, int, int, off_t); + mmap_fn real_mmap = (mmap_fn)dlsym(RTLD_NEXT, "mmap"); + + // Allocate the page that was released to the OS in free() with the real mmap, + // bypassing the interceptor. + char *q = (char *)real_mmap(p, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); + ASSERT_NE((char *)0, q); + + ASSERT_TRUE(q <= p); + ASSERT_TRUE(q + 4096 > p); + + EXPECT_NOT_POISONED(q[0]); + EXPECT_NOT_POISONED(q[10]); + EXPECT_NOT_POISONED(q[100]); + + munmap(q, 4096); +}