Skip to content

Commit 613a09c

Browse files
committed
[scudo] Always zero on linux even if the memory cannot be released.
If a caller has locked memory, then the madvise call will fail. In that case, zero the memory so that we don't return non-zeroed memory for calloc calls since we thought the memory had been released.
1 parent 2e489f7 commit 613a09c

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

compiler-rt/lib/scudo/standalone/mem_map_linux.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,12 @@ void MemMapLinux::setMemoryPermissionImpl(uptr Addr, uptr Size, uptr Flags) {
122122
void MemMapLinux::releaseAndZeroPagesToOSImpl(uptr From, uptr Size) {
123123
void *Addr = reinterpret_cast<void *>(From);
124124

125-
while (madvise(Addr, Size, MADV_DONTNEED) == -1 && errno == EAGAIN) {
125+
int rc;
126+
while ((rc = madvise(Addr, Size, MADV_DONTNEED)) == -1 && errno == EAGAIN) {
127+
}
128+
if (rc == -1) {
129+
// If we can't madvies the memory, then we still need to zero it.
130+
memset(Addr, 0, Size);
126131
}
127132
}
128133

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
#include <string.h>
1515
#include <unistd.h>
1616

17+
#if SCUDO_LINUX
18+
#include <sys/mman.h>
19+
#endif
20+
1721
static const char *MappingName = "scudo:test";
1822

1923
TEST(ScudoMapTest, PageSize) {
@@ -89,3 +93,40 @@ TEST(ScudoMapTest, MapGrowUnmap) {
8993
memset(reinterpret_cast<void *>(Q), 0xbb, PageSize);
9094
MemMap.unmap();
9195
}
96+
97+
// Verify that zeroing works properly.
98+
TEST(ScudoMapTest, Zeroing) {
99+
scudo::ReservedMemoryT ReservedMemory;
100+
const scudo::uptr PageSize = scudo::getPageSizeCached();
101+
const scudo::uptr Size = 3 * PageSize;
102+
ReservedMemory.create(/*Addr=*/0U, Size, MappingName);
103+
ASSERT_TRUE(ReservedMemory.isCreated());
104+
105+
scudo::MemMapT MemMap = ReservedMemory.dispatch(ReservedMemory.getBase(), ReservedMemory.getCapacity());
106+
EXPECT_TRUE(MemMap.remap(MemMap.getBase(), MemMap.getCapacity(), MappingName));
107+
unsigned char *Data = reinterpret_cast<unsigned char*>(MemMap.getBase());
108+
memset(Data, 1U, MemMap.getCapacity());
109+
// Spot check some values.
110+
EXPECT_EQ(1U, Data[0]);
111+
EXPECT_EQ(1U, Data[PageSize]);
112+
EXPECT_EQ(1U, Data[PageSize * 2]);
113+
MemMap.releaseAndZeroPagesToOS(MemMap.getBase(), MemMap.getCapacity());
114+
EXPECT_EQ(0U, Data[0]);
115+
EXPECT_EQ(0U, Data[PageSize]);
116+
EXPECT_EQ(0U, Data[PageSize * 2]);
117+
118+
#if SCUDO_LINUX
119+
// Now verify that if madvise fails, the data is still zeroed.
120+
memset(Data, 1U, MemMap.getCapacity());
121+
EXPECT_NE(-1, mlock(Data, MemMap.getCapacity()));
122+
EXPECT_EQ(1U, Data[0]);
123+
EXPECT_EQ(1U, Data[PageSize]);
124+
EXPECT_EQ(1U, Data[PageSize * 2]);
125+
MemMap.releaseAndZeroPagesToOS(MemMap.getBase(), MemMap.getCapacity());
126+
EXPECT_EQ(0U, Data[0]);
127+
EXPECT_EQ(0U, Data[PageSize]);
128+
EXPECT_EQ(0U, Data[PageSize * 2]);
129+
#endif
130+
131+
MemMap.unmap();
132+
}

0 commit comments

Comments
 (0)