Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b74f615

Browse files
thurstondtstellar
authored andcommitted
[msan] Add 'MappingDesc::ALLOCATOR' type and check it is available (llvm#85153)
MSan divides the virtual address space into APP, INVALID, SHADOW and ORIGIN memory. The allocator usually just steals a bit of the APP address space: typically the bottom portion of the PIE binaries section, which works because the Linux kernel maps from the top of the PIE binaries section. However, if ASLR is very aggressive, the binary may end up mapped in the same location where the allocator wants to live; this results in a segfault. This patch adds in a MappingDesc::ALLOCATOR type and enforces that the memory range for the allocator is not occupied by anything else. Since the allocator range information is not readily available in msan.h, we duplicate the information from msan_allocator.cpp. Note: aggressive ASLR can also lead to a different type of failure, where the PIE binaries/libraries are mapped entirely outside of the APP/ALLOCATOR sections; that will be addressed in a separate patch (llvm#85142). (cherry picked from commit af2bf86)
1 parent 98a15dd commit b74f615

File tree

3 files changed

+34
-13
lines changed

3 files changed

+34
-13
lines changed

compiler-rt/lib/msan/msan.h

+23-10
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,18 @@ struct MappingDesc {
3333
uptr start;
3434
uptr end;
3535
enum Type {
36-
INVALID, APP, SHADOW, ORIGIN
36+
INVALID = 1,
37+
ALLOCATOR = 2,
38+
APP = 4,
39+
SHADOW = 8,
40+
ORIGIN = 16,
3741
} type;
3842
const char *name;
3943
};
4044

41-
45+
// Note: MappingDesc::ALLOCATOR entries are only used to check for memory
46+
// layout compatibility. The actual allocation settings are in
47+
// msan_allocator.cpp, which need to be kept in sync.
4248
#if SANITIZER_LINUX && defined(__mips64)
4349

4450
// MIPS64 maps:
@@ -84,7 +90,8 @@ const MappingDesc kMemoryLayout[] = {
8490
{0X0B00000000000, 0X0C00000000000, MappingDesc::SHADOW, "shadow-10-13"},
8591
{0X0C00000000000, 0X0D00000000000, MappingDesc::INVALID, "invalid"},
8692
{0X0D00000000000, 0X0E00000000000, MappingDesc::ORIGIN, "origin-10-13"},
87-
{0X0E00000000000, 0X1000000000000, MappingDesc::APP, "app-15"},
93+
{0x0E00000000000, 0x0E40000000000, MappingDesc::ALLOCATOR, "allocator"},
94+
{0X0E40000000000, 0X1000000000000, MappingDesc::APP, "app-15"},
8895
};
8996
# define MEM_TO_SHADOW(mem) ((uptr)mem ^ 0xB00000000000ULL)
9097
# define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x200000000000ULL)
@@ -106,7 +113,8 @@ const MappingDesc kMemoryLayout[] = {
106113
{0x510000000000ULL, 0x600000000000ULL, MappingDesc::APP, "app-2"},
107114
{0x600000000000ULL, 0x610000000000ULL, MappingDesc::ORIGIN, "origin-1"},
108115
{0x610000000000ULL, 0x700000000000ULL, MappingDesc::INVALID, "invalid"},
109-
{0x700000000000ULL, 0x800000000000ULL, MappingDesc::APP, "app-3"}};
116+
{0x700000000000ULL, 0x740000000000ULL, MappingDesc::ALLOCATOR, "allocator"},
117+
{0x740000000000ULL, 0x800000000000ULL, MappingDesc::APP, "app-3"}};
110118
# define MEM_TO_SHADOW(mem) (((uptr)(mem)) ^ 0x500000000000ULL)
111119
# define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x100000000000ULL)
112120

@@ -118,7 +126,8 @@ const MappingDesc kMemoryLayout[] = {
118126
{0x180200000000ULL, 0x1C0000000000ULL, MappingDesc::INVALID, "invalid"},
119127
{0x1C0000000000ULL, 0x2C0200000000ULL, MappingDesc::ORIGIN, "origin"},
120128
{0x2C0200000000ULL, 0x300000000000ULL, MappingDesc::INVALID, "invalid"},
121-
{0x300000000000ULL, 0x800000000000ULL, MappingDesc::APP, "high memory"}};
129+
{0x300000000000ULL, 0x320000000000ULL, MappingDesc::ALLOCATOR, "allocator"},
130+
{0x320000000000ULL, 0x800000000000ULL, MappingDesc::APP, "high memory"}};
122131

123132
// Various kernels use different low end ranges but we can combine them into one
124133
// big range. They also use different high end ranges but we can map them all to
@@ -141,7 +150,8 @@ const MappingDesc kMemoryLayout[] = {
141150
{0x180000000000ULL, 0x1C0000000000ULL, MappingDesc::INVALID, "invalid"},
142151
{0x1C0000000000ULL, 0x2C0000000000ULL, MappingDesc::ORIGIN, "origin"},
143152
{0x2C0000000000ULL, 0x440000000000ULL, MappingDesc::INVALID, "invalid"},
144-
{0x440000000000ULL, 0x500000000000ULL, MappingDesc::APP, "high memory"}};
153+
{0x440000000000ULL, 0x460000000000ULL, MappingDesc::ALLOCATOR, "allocator"},
154+
{0x460000000000ULL, 0x500000000000ULL, MappingDesc::APP, "high memory"}};
145155

146156
#define MEM_TO_SHADOW(mem) \
147157
((((uptr)(mem)) & ~0xC00000000000ULL) + 0x080000000000ULL)
@@ -208,7 +218,8 @@ const MappingDesc kMemoryLayout[] = {
208218
{0x510000000000ULL, 0x600000000000ULL, MappingDesc::APP, "app-2"},
209219
{0x600000000000ULL, 0x610000000000ULL, MappingDesc::ORIGIN, "origin-1"},
210220
{0x610000000000ULL, 0x700000000000ULL, MappingDesc::INVALID, "invalid"},
211-
{0x700000000000ULL, 0x800000000000ULL, MappingDesc::APP, "app-3"}};
221+
{0x700000000000ULL, 0x740000000000ULL, MappingDesc::ALLOCATOR, "allocator"},
222+
{0x740000000000ULL, 0x800000000000ULL, MappingDesc::APP, "app-3"}};
212223
#define MEM_TO_SHADOW(mem) (((uptr)(mem)) ^ 0x500000000000ULL)
213224
#define SHADOW_TO_ORIGIN(mem) (((uptr)(mem)) + 0x100000000000ULL)
214225

@@ -223,20 +234,22 @@ const uptr kMemoryLayoutSize = sizeof(kMemoryLayout) / sizeof(kMemoryLayout[0]);
223234
#ifndef __clang__
224235
__attribute__((optimize("unroll-loops")))
225236
#endif
226-
inline bool addr_is_type(uptr addr, MappingDesc::Type mapping_type) {
237+
inline bool
238+
addr_is_type(uptr addr, int mapping_types) {
227239
// It is critical for performance that this loop is unrolled (because then it is
228240
// simplified into just a few constant comparisons).
229241
#ifdef __clang__
230242
#pragma unroll
231243
#endif
232244
for (unsigned i = 0; i < kMemoryLayoutSize; ++i)
233-
if (kMemoryLayout[i].type == mapping_type &&
245+
if ((kMemoryLayout[i].type & mapping_types) &&
234246
addr >= kMemoryLayout[i].start && addr < kMemoryLayout[i].end)
235247
return true;
236248
return false;
237249
}
238250

239-
#define MEM_IS_APP(mem) addr_is_type((uptr)(mem), MappingDesc::APP)
251+
#define MEM_IS_APP(mem) \
252+
(addr_is_type((uptr)(mem), MappingDesc::APP | MappingDesc::ALLOCATOR))
240253
#define MEM_IS_SHADOW(mem) addr_is_type((uptr)(mem), MappingDesc::SHADOW)
241254
#define MEM_IS_ORIGIN(mem) addr_is_type((uptr)(mem), MappingDesc::ORIGIN)
242255

compiler-rt/lib/msan/msan_allocator.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ struct MsanMapUnmapCallback {
4848
}
4949
};
5050

51+
// Note: to ensure that the allocator is compatible with the application memory
52+
// layout (especially with high-entropy ASLR), kSpaceBeg and kSpaceSize must be
53+
// duplicated as MappingDesc::ALLOCATOR in msan.h.
5154
#if defined(__mips64)
5255
static const uptr kMaxAllowedMallocSize = 2UL << 30;
5356

compiler-rt/lib/msan/msan_linux.cpp

+8-3
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ static void CheckMemoryLayoutSanity() {
8686
CHECK(addr_is_type(start, type));
8787
CHECK(addr_is_type((start + end) / 2, type));
8888
CHECK(addr_is_type(end - 1, type));
89-
if (type == MappingDesc::APP) {
89+
if (type == MappingDesc::APP || type == MappingDesc::ALLOCATOR) {
9090
uptr addr = start;
9191
CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)));
9292
CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)));
@@ -138,8 +138,13 @@ bool InitShadow(bool init_origins) {
138138
bool protect = type == MappingDesc::INVALID ||
139139
(!init_origins && type == MappingDesc::ORIGIN);
140140
CHECK(!(map && protect));
141-
if (!map && !protect)
142-
CHECK(type == MappingDesc::APP);
141+
if (!map && !protect) {
142+
CHECK(type == MappingDesc::APP || type == MappingDesc::ALLOCATOR);
143+
144+
if (type == MappingDesc::ALLOCATOR &&
145+
!CheckMemoryRangeAvailability(start, size))
146+
return false;
147+
}
143148
if (map) {
144149
if (!CheckMemoryRangeAvailability(start, size))
145150
return false;

0 commit comments

Comments
 (0)