[msan] Unpoison memory that is returned to the OS and flush its shadow.

llvm-svn: 195244
This commit is contained in:
Evgeniy Stepanov 2013-11-20 12:51:14 +00:00
parent 115ef14548
commit 584fd96e9e
2 changed files with 39 additions and 2 deletions

View File

@ -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;

View File

@ -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);
}