Skip to content

Commit adcd285

Browse files
authored
[scudo] Return nullptr if a remap fails on linux. (#200537)
Add a check if a fixed address mmap doesn't return the expected address. Allow a remap call to fail if the mmap fails and returns a nullptr to the caller. Fix a place where if remap fails in the secondary, it didn't do anything. Now it will unmap the original entry on failure.
1 parent f3bed42 commit adcd285

5 files changed

Lines changed: 27 additions & 5 deletions

File tree

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ static void *mmapWrapper(uptr Addr, uptr Size, const char *Name, uptr Flags) {
6868
reportMapError(errno == ENOMEM ? Size : 0);
6969
return nullptr;
7070
}
71+
72+
if (Addr && reinterpret_cast<uptr>(P) != Addr)
73+
reportMapFixedError(reinterpret_cast<uptr>(P), Addr);
74+
7175
#if SCUDO_ANDROID
7276
if (Name)
7377
prctl(ANDROID_PR_SET_VMA, ANDROID_PR_SET_VMA_ANON_NAME, P, Size, Name);
@@ -108,9 +112,7 @@ void MemMapLinux::unmapImpl(uptr Addr, uptr Size) {
108112
bool MemMapLinux::remapImpl(uptr Addr, uptr Size, const char *Name,
109113
uptr Flags) {
110114
void *P = mmapWrapper(Addr, Size, Name, Flags);
111-
if (reinterpret_cast<uptr>(P) != Addr)
112-
reportMapError();
113-
return true;
115+
return reinterpret_cast<uptr>(P) == Addr;
114116
}
115117

116118
void MemMapLinux::setMemoryPermissionImpl(uptr Addr, uptr Size, uptr Flags) {

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ void NORETURN reportMapError(uptr SizeIfOOM) {
3333
reportRawError(Error.data());
3434
}
3535

36+
void NORETURN reportMapFixedError(uptr ExpectedAddr, uptr RequestedAddr) {
37+
ScopedString Error;
38+
Error.append("Scudo ERROR: internal map failure using fixed address "
39+
"(expected: 0x%zx requested: 0x%zx)\n",
40+
ExpectedAddr, RequestedAddr);
41+
reportRawError(Error.data());
42+
}
43+
3644
void NORETURN reportUnmapError(uptr Addr, uptr Size) {
3745
ScopedString Error;
3846
Error.append("Scudo ERROR: internal unmap failure (error desc=%s) Addr 0x%zx "

compiler-rt/lib/scudo/standalone/report_linux.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ namespace scudo {
2121
// hold the requested size on an out-of-memory error, 0 otherwise.
2222
void NORETURN reportMapError(uptr SizeIfOOM = 0);
2323

24+
// Report a fatal error when a map call using a fixed address doesn't
25+
// return the requested address.
26+
void NORETURN reportMapFixedError(uptr ExpectedAddr, uptr RequestedAddr);
27+
2428
// Report a fatal error when an unmap call fails.
2529
void NORETURN reportUnmapError(uptr Addr, uptr Size);
2630

compiler-rt/lib/scudo/standalone/secondary.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,8 +306,13 @@ class MapAllocatorCache {
306306
// Fuchsia does not support replacing mappings by creating a new mapping
307307
// on top so we just do the two syscalls there.
308308
Entry.Time = 0;
309-
mapSecondary<Config>(Options, Entry.CommitBase, Entry.CommitSize,
310-
Entry.CommitBase, MAP_NOACCESS, Entry.MemMap);
309+
if (!mapSecondary<Config>(Options, Entry.CommitBase, Entry.CommitSize,
310+
Entry.CommitBase, MAP_NOACCESS,
311+
Entry.MemMap)) {
312+
// A mmap failed, unmap and return.
313+
unmapCallBack(Entry.MemMap);
314+
return;
315+
}
311316
} else {
312317
Entry.MemMap.setMemoryPermission(Entry.CommitBase, Entry.CommitSize,
313318
MAP_NOACCESS);

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ TEST(ScudoReportDeathTest, Linux) {
105105
EXPECT_DEATH(scudo::reportMapError(1024U),
106106
"Scudo ERROR:.*internal map failure \\(error desc=.*\\) "
107107
"requesting 1KB");
108+
EXPECT_DEATH(scudo::reportMapFixedError(0x1000U, 0x2000U),
109+
"Scudo ERROR:.*internal map failure using fixed address "
110+
"\\(expected: 0x1000 requested: 0x2000\\)");
108111
errno = ENOMEM;
109112
EXPECT_DEATH(scudo::reportUnmapError(0x1000U, 100U),
110113
"Scudo ERROR:.*internal unmap failure \\(error desc=.*\\) Addr "

0 commit comments

Comments
 (0)