Skip to content

Commit 99d92d1

Browse files
authored
[scudo] Add specific die functions for linux specific failures. (#68650)
While running into failures on unmap calls, it becomes difficult to figure out what's wrong. Break the dieOnMapUnmapError into specific versions for map, unmap, and then one for mprotect. Also, put these in a common linux space so that all linux derived code can reuse this code.
1 parent 6dbc6df commit 99d92d1

File tree

10 files changed

+119
-34
lines changed

10 files changed

+119
-34
lines changed

compiler-rt/lib/scudo/standalone/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ set(SCUDO_HEADERS
8484
quarantine.h
8585
release.h
8686
report.h
87+
report_linux.h
8788
secondary.h
8889
size_class_map.h
8990
stack_depot.h
@@ -113,6 +114,7 @@ set(SCUDO_SOURCES
113114
mem_map_linux.cpp
114115
release.cpp
115116
report.cpp
117+
report_linux.cpp
116118
string_utils.cpp
117119
timing.cpp
118120
)

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

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,4 @@ uptr getPageSizeSlow() {
2121
return PageSizeCached;
2222
}
2323

24-
// Fatal internal map() or unmap() error (potentially OOM related).
25-
void NORETURN dieOnMapUnmapError(uptr SizeIfOOM) {
26-
char Error[128] = "Scudo ERROR: internal map or unmap failure\n";
27-
if (SizeIfOOM) {
28-
formatString(
29-
Error, sizeof(Error),
30-
"Scudo ERROR: internal map failure (NO MEMORY) requesting %zuKB\n",
31-
SizeIfOOM >> 10);
32-
}
33-
outputRaw(Error);
34-
setAbortMessage(Error);
35-
die();
36-
}
37-
3824
} // namespace scudo

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,10 +175,6 @@ void setMemoryPermission(uptr Addr, uptr Size, uptr Flags,
175175
void releasePagesToOS(uptr BaseAddress, uptr Offset, uptr Size,
176176
MapPlatformData *Data = nullptr);
177177

178-
// Internal map & unmap fatal error. This must not call map(). SizeIfOOM shall
179-
// hold the requested size on an out-of-memory error, 0 otherwise.
180-
void NORETURN dieOnMapUnmapError(uptr SizeIfOOM = 0);
181-
182178
// Logging related functions.
183179

184180
void setAbortMessage(const char *Message);

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "internal_defs.h"
1515
#include "linux.h"
1616
#include "mutex.h"
17+
#include "report_linux.h"
1718
#include "string_utils.h"
1819

1920
#include <errno.h>
@@ -66,7 +67,7 @@ void *map(void *Addr, uptr Size, UNUSED const char *Name, uptr Flags,
6667
void *P = mmap(Addr, Size, MmapProt, MmapFlags, -1, 0);
6768
if (P == MAP_FAILED) {
6869
if (!(Flags & MAP_ALLOWNOMEM) || errno != ENOMEM)
69-
dieOnMapUnmapError(errno == ENOMEM ? Size : 0);
70+
reportMapError(errno == ENOMEM ? Size : 0);
7071
return nullptr;
7172
}
7273
#if SCUDO_ANDROID
@@ -80,15 +81,15 @@ void *map(void *Addr, uptr Size, UNUSED const char *Name, uptr Flags,
8081
void unmap(void *Addr, uptr Size, UNUSED uptr Flags,
8182
UNUSED MapPlatformData *Data) {
8283
if (munmap(Addr, Size) != 0)
83-
dieOnMapUnmapError();
84+
reportUnmapError(reinterpret_cast<uptr>(Addr), Size);
8485
}
8586

8687
// TODO: Will be deprecated. Use the interfaces in MemMapLinux instead.
8788
void setMemoryPermission(uptr Addr, uptr Size, uptr Flags,
8889
UNUSED MapPlatformData *Data) {
8990
int Prot = (Flags & MAP_NOACCESS) ? PROT_NONE : (PROT_READ | PROT_WRITE);
9091
if (mprotect(reinterpret_cast<void *>(Addr), Size, Prot) != 0)
91-
dieOnMapUnmapError();
92+
reportProtectError(Addr, Size, Prot);
9293
}
9394

9495
// TODO: Will be deprecated. Use the interfaces in MemMapLinux instead.

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "internal_defs.h"
1717
#include "linux.h"
1818
#include "mutex.h"
19+
#include "report_linux.h"
1920
#include "string_utils.h"
2021

2122
#include <errno.h>
@@ -64,7 +65,7 @@ static void *mmapWrapper(uptr Addr, uptr Size, const char *Name, uptr Flags) {
6465
mmap(reinterpret_cast<void *>(Addr), Size, MmapProt, MmapFlags, -1, 0);
6566
if (P == MAP_FAILED) {
6667
if (!(Flags & MAP_ALLOWNOMEM) || errno != ENOMEM)
67-
dieOnMapUnmapError(errno == ENOMEM ? Size : 0);
68+
reportMapError(errno == ENOMEM ? Size : 0);
6869
return nullptr;
6970
}
7071
#if SCUDO_ANDROID
@@ -101,21 +102,21 @@ void MemMapLinux::unmapImpl(uptr Addr, uptr Size) {
101102
}
102103

103104
if (munmap(reinterpret_cast<void *>(Addr), Size) != 0)
104-
dieOnMapUnmapError();
105+
reportUnmapError(Addr, Size);
105106
}
106107

107108
bool MemMapLinux::remapImpl(uptr Addr, uptr Size, const char *Name,
108109
uptr Flags) {
109110
void *P = mmapWrapper(Addr, Size, Name, Flags);
110111
if (reinterpret_cast<uptr>(P) != Addr)
111-
dieOnMapUnmapError();
112+
reportMapError();
112113
return true;
113114
}
114115

115116
void MemMapLinux::setMemoryPermissionImpl(uptr Addr, uptr Size, uptr Flags) {
116117
int Prot = (Flags & MAP_NOACCESS) ? PROT_NONE : (PROT_READ | PROT_WRITE);
117118
if (mprotect(reinterpret_cast<void *>(Addr), Size, Prot) != 0)
118-
dieOnMapUnmapError();
119+
reportProtectError(Addr, Size, Prot);
119120
}
120121

121122
void MemMapLinux::releaseAndZeroPagesToOSImpl(uptr From, uptr Size) {
@@ -139,7 +140,7 @@ bool ReservedMemoryLinux::createImpl(uptr Addr, uptr Size, const char *Name,
139140

140141
void ReservedMemoryLinux::releaseImpl() {
141142
if (munmap(reinterpret_cast<void *>(getBase()), getCapacity()) != 0)
142-
dieOnMapUnmapError();
143+
reportUnmapError(getBase(), getCapacity());
143144
}
144145

145146
ReservedMemoryLinux::MemMapT ReservedMemoryLinux::dispatchImpl(uptr Addr,

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,7 @@ class ScopedErrorReport {
2424
Message.vappend(Format, Args);
2525
va_end(Args);
2626
}
27-
NORETURN ~ScopedErrorReport() {
28-
outputRaw(Message.data());
29-
setAbortMessage(Message.data());
30-
die();
31-
}
27+
NORETURN ~ScopedErrorReport() { reportRawError(Message.data()); }
3228

3329
private:
3430
ScopedString Message;
@@ -55,6 +51,13 @@ void NORETURN reportError(const char *Message) {
5551
Report.append("%s\n", Message);
5652
}
5753

54+
// Generic fatal error message without ScopedString.
55+
void NORETURN reportRawError(const char *Message) {
56+
outputRaw(Message);
57+
setAbortMessage(Message);
58+
die();
59+
}
60+
5861
void NORETURN reportInvalidFlag(const char *FlagType, const char *Value) {
5962
ScopedErrorReport Report;
6063
Report.append("invalid value for %s option: '%s'\n", FlagType, Value);

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@ namespace scudo {
1515

1616
// Reports are *fatal* unless stated otherwise.
1717

18-
// Generic error.
18+
// Generic error, adds newline to end of message.
1919
void NORETURN reportError(const char *Message);
2020

21+
// Generic error, but the message is not modified.
22+
void NORETURN reportRawError(const char *Message);
23+
2124
// Flags related errors.
2225
void NORETURN reportInvalidFlag(const char *FlagType, const char *Value);
2326

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//===-- report_linux.cpp ----------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "platform.h"
10+
11+
#if SCUDO_LINUX || SCUDO_TRUSTY
12+
13+
#include "common.h"
14+
#include "internal_defs.h"
15+
#include "report.h"
16+
#include "report_linux.h"
17+
#include "string_utils.h"
18+
19+
#include <errno.h>
20+
#include <stdlib.h>
21+
#include <string.h>
22+
23+
namespace scudo {
24+
25+
// Fatal internal map() error (potentially OOM related).
26+
void NORETURN reportMapError(uptr SizeIfOOM) {
27+
char Error[128] = "Scudo ERROR: internal map failure\n";
28+
if (SizeIfOOM) {
29+
formatString(
30+
Error, sizeof(Error),
31+
"Scudo ERROR: internal map failure (NO MEMORY) requesting %zuKB\n",
32+
SizeIfOOM >> 10);
33+
}
34+
reportRawError(Error);
35+
}
36+
37+
void NORETURN reportUnmapError(uptr Addr, uptr Size) {
38+
char Error[128];
39+
formatString(Error, sizeof(Error),
40+
"Scudo ERROR: internal unmap failure (error desc=%s) Addr 0x%zx "
41+
"Size %zu\n",
42+
strerror(errno), Addr, Size);
43+
reportRawError(Error);
44+
}
45+
46+
void NORETURN reportProtectError(uptr Addr, uptr Size, int Prot) {
47+
char Error[128];
48+
formatString(
49+
Error, sizeof(Error),
50+
"Scudo ERROR: internal protect failure (error desc=%s) Addr 0x%zx "
51+
"Size %zu Prot %x\n",
52+
strerror(errno), Addr, Size, Prot);
53+
reportRawError(Error);
54+
}
55+
56+
} // namespace scudo
57+
58+
#endif // SCUDO_LINUX || SCUDO_TRUSTY
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//===-- report_linux.h ------------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef SCUDO_REPORT_LINUX_H_
10+
#define SCUDO_REPORT_LINUX_H_
11+
12+
#include "platform.h"
13+
14+
#if SCUDO_LINUX || SCUDO_TRUSTY
15+
16+
#include "internal_defs.h"
17+
18+
namespace scudo {
19+
20+
// Report a fatal error when a map call fails. SizeIfOOM shall
21+
// hold the requested size on an out-of-memory error, 0 otherwise.
22+
void NORETURN reportMapError(uptr SizeIfOOM = 0);
23+
24+
// Report a fatal error when an unmap call fails.
25+
void NORETURN reportUnmapError(uptr Addr, uptr Size);
26+
27+
// Report a fatal error when a mprotect call fails.
28+
void NORETURN reportProtectError(uptr Addr, uptr Size, int Prot);
29+
30+
} // namespace scudo
31+
32+
#endif // SCUDO_LINUX || SCUDO_TRUSTY
33+
34+
#endif // SCUDO_REPORT_LINUX_H_

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "common.h"
1414
#include "mutex.h"
15+
#include "report_linux.h"
1516
#include "trusty.h"
1617

1718
#include <errno.h> // for errno
@@ -51,7 +52,7 @@ void *map(void *Addr, uptr Size, const char *Name, uptr Flags,
5152
if (IS_ERR(P)) {
5253
errno = lk_err_to_errno(PTR_ERR(P));
5354
if (!(Flags & MAP_ALLOWNOMEM) || errno != ENOMEM)
54-
dieOnMapUnmapError(Size);
55+
reportMapError(Size);
5556
return nullptr;
5657
}
5758

@@ -61,7 +62,7 @@ void *map(void *Addr, uptr Size, const char *Name, uptr Flags,
6162
void unmap(UNUSED void *Addr, UNUSED uptr Size, UNUSED uptr Flags,
6263
UNUSED MapPlatformData *Data) {
6364
if (_trusty_munmap(Addr, Size) != 0)
64-
dieOnMapUnmapError();
65+
reportUnmapError(Addr, Size);
6566
}
6667

6768
void setMemoryPermission(UNUSED uptr Addr, UNUSED uptr Size, UNUSED uptr Flags,

0 commit comments

Comments
 (0)