diff --git a/compiler-rt/lib/scudo/standalone/mem_map_linux.cpp b/compiler-rt/lib/scudo/standalone/mem_map_linux.cpp index 783c4f0d9ab0f..df3e54cab6695 100644 --- a/compiler-rt/lib/scudo/standalone/mem_map_linux.cpp +++ b/compiler-rt/lib/scudo/standalone/mem_map_linux.cpp @@ -122,7 +122,12 @@ void MemMapLinux::setMemoryPermissionImpl(uptr Addr, uptr Size, uptr Flags) { void MemMapLinux::releaseAndZeroPagesToOSImpl(uptr From, uptr Size) { void *Addr = reinterpret_cast(From); - while (madvise(Addr, Size, MADV_DONTNEED) == -1 && errno == EAGAIN) { + int rc; + while ((rc = madvise(Addr, Size, MADV_DONTNEED)) == -1 && errno == EAGAIN) { + } + if (rc == -1) { + // If we can't madvies the memory, then we still need to zero it. + memset(Addr, 0, Size); } } diff --git a/compiler-rt/lib/scudo/standalone/tests/map_test.cpp b/compiler-rt/lib/scudo/standalone/tests/map_test.cpp index cc7d3ee4dc6c2..afdfe5be85fb6 100644 --- a/compiler-rt/lib/scudo/standalone/tests/map_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/map_test.cpp @@ -14,6 +14,10 @@ #include #include +#if SCUDO_LINUX +#include +#endif + static const char *MappingName = "scudo:test"; TEST(ScudoMapTest, PageSize) { @@ -89,3 +93,45 @@ TEST(ScudoMapTest, MapGrowUnmap) { memset(reinterpret_cast(Q), 0xbb, PageSize); MemMap.unmap(); } + +// Verify that zeroing works properly. +TEST(ScudoMapTest, Zeroing) { + scudo::ReservedMemoryT ReservedMemory; + const scudo::uptr PageSize = scudo::getPageSizeCached(); + const scudo::uptr Size = 3 * PageSize; + ReservedMemory.create(/*Addr=*/0U, Size, MappingName); + ASSERT_TRUE(ReservedMemory.isCreated()); + + scudo::MemMapT MemMap = ReservedMemory.dispatch(ReservedMemory.getBase(), + ReservedMemory.getCapacity()); + EXPECT_TRUE( + MemMap.remap(MemMap.getBase(), MemMap.getCapacity(), MappingName)); + unsigned char *Data = reinterpret_cast(MemMap.getBase()); + memset(Data, 1U, MemMap.getCapacity()); + // Spot check some values. + EXPECT_EQ(1U, Data[0]); + EXPECT_EQ(1U, Data[PageSize]); + EXPECT_EQ(1U, Data[PageSize * 2]); + MemMap.releaseAndZeroPagesToOS(MemMap.getBase(), MemMap.getCapacity()); + EXPECT_EQ(0U, Data[0]); + EXPECT_EQ(0U, Data[PageSize]); + EXPECT_EQ(0U, Data[PageSize * 2]); + +#if SCUDO_LINUX + // Now verify that if madvise fails, the data is still zeroed. + memset(Data, 1U, MemMap.getCapacity()); + EXPECT_NE(-1, mlock(Data, MemMap.getCapacity())); + + EXPECT_EQ(1U, Data[0]); + EXPECT_EQ(1U, Data[PageSize]); + EXPECT_EQ(1U, Data[PageSize * 2]); + MemMap.releaseAndZeroPagesToOS(MemMap.getBase(), MemMap.getCapacity()); + EXPECT_EQ(0U, Data[0]); + EXPECT_EQ(0U, Data[PageSize]); + EXPECT_EQ(0U, Data[PageSize * 2]); + + EXPECT_NE(-1, munlock(Data, MemMap.getCapacity())); +#endif + + MemMap.unmap(); +}