diff options
-rw-r--r-- | compiler-rt/lib/msan/msan_allocator.cc | 18 | ||||
-rw-r--r-- | 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 2badf712188..3c74142bcb1 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<kAllocatorSpace, kAllocatorSize, kMetadataSize, - DefaultSizeClassMap> PrimaryAllocator; + DefaultSizeClassMap, + MsanMapUnmapCallback> PrimaryAllocator; typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache; -typedef LargeMmapAllocator<> SecondaryAllocator; +typedef LargeMmapAllocator<MsanMapUnmapCallback> SecondaryAllocator; typedef CombinedAllocator<PrimaryAllocator, AllocatorCache, SecondaryAllocator> Allocator; diff --git a/compiler-rt/lib/msan/tests/msan_test.cc b/compiler-rt/lib/msan/tests/msan_test.cc index e555fec0bef..a60a232110e 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); +} |