20
20
# include < signal.h>
21
21
# include < stdio.h>
22
22
# include < stdlib.h>
23
+ # if SANITIZER_LINUX
24
+ # include < sys/personality.h>
25
+ # endif
23
26
# include < sys/resource.h>
24
27
# include < sys/time.h>
25
28
# include < unistd.h>
@@ -43,11 +46,13 @@ void ReportMapRange(const char *descr, uptr beg, uptr size) {
43
46
}
44
47
}
45
48
46
- static bool CheckMemoryRangeAvailability (uptr beg, uptr size) {
49
+ static bool CheckMemoryRangeAvailability (uptr beg, uptr size, bool verbose ) {
47
50
if (size > 0 ) {
48
51
uptr end = beg + size - 1 ;
49
52
if (!MemoryRangeIsAvailable (beg, end)) {
50
- Printf (" FATAL: Memory range 0x%zx - 0x%zx is not available.\n " , beg, end);
53
+ if (verbose)
54
+ Printf (" FATAL: Memory range 0x%zx - 0x%zx is not available.\n " , beg,
55
+ end);
51
56
return false ;
52
57
}
53
58
}
@@ -106,7 +111,7 @@ static void CheckMemoryLayoutSanity() {
106
111
}
107
112
}
108
113
109
- bool InitShadow (bool init_origins) {
114
+ static bool InitShadow (bool init_origins, bool dry_run ) {
110
115
// Let user know mapping parameters first.
111
116
VPrintf (1 , " __msan_init %p\n " , reinterpret_cast <void *>(&__msan_init));
112
117
for (unsigned i = 0 ; i < kMemoryLayoutSize ; ++i)
@@ -116,8 +121,9 @@ bool InitShadow(bool init_origins) {
116
121
CheckMemoryLayoutSanity ();
117
122
118
123
if (!MEM_IS_APP (&__msan_init)) {
119
- Printf (" FATAL: Code %p is out of application range. Non-PIE build?\n " ,
120
- reinterpret_cast <void *>(&__msan_init));
124
+ if (!dry_run)
125
+ Printf (" FATAL: Code %p is out of application range. Non-PIE build?\n " ,
126
+ reinterpret_cast <void *>(&__msan_init));
121
127
return false ;
122
128
}
123
129
@@ -141,29 +147,59 @@ bool InitShadow(bool init_origins) {
141
147
if (!map && !protect) {
142
148
CHECK (type == MappingDesc::APP || type == MappingDesc::ALLOCATOR);
143
149
144
- if (type == MappingDesc::ALLOCATOR &&
145
- !CheckMemoryRangeAvailability (start, size))
150
+ if (dry_run && type == MappingDesc::ALLOCATOR &&
151
+ !CheckMemoryRangeAvailability (start, size, !dry_run ))
146
152
return false ;
147
153
}
148
154
if (map) {
149
- if (!CheckMemoryRangeAvailability (start, size))
155
+ if (dry_run && !CheckMemoryRangeAvailability (start, size, !dry_run ))
150
156
return false ;
151
- if (!MmapFixedSuperNoReserve (start, size, kMemoryLayout [i].name ))
157
+ if (!dry_run &&
158
+ !MmapFixedSuperNoReserve (start, size, kMemoryLayout [i].name ))
152
159
return false ;
153
- if (common_flags ()->use_madv_dontdump )
160
+ if (!dry_run && common_flags ()->use_madv_dontdump )
154
161
DontDumpShadowMemory (start, size);
155
162
}
156
163
if (protect) {
157
- if (!CheckMemoryRangeAvailability (start, size))
164
+ if (dry_run && !CheckMemoryRangeAvailability (start, size, !dry_run ))
158
165
return false ;
159
- if (!ProtectMemoryRange (start, size, kMemoryLayout [i].name ))
166
+ if (!dry_run && ! ProtectMemoryRange (start, size, kMemoryLayout [i].name ))
160
167
return false ;
161
168
}
162
169
}
163
170
164
171
return true ;
165
172
}
166
173
174
+ bool InitShadowWithReExec (bool init_origins) {
175
+ // Start with dry run: check layout is ok, but don't print warnings because
176
+ // warning messages will cause tests to fail (even if we successfully re-exec
177
+ // after the warning).
178
+ bool success = InitShadow (__msan_get_track_origins (), true );
179
+ if (!success) {
180
+ # if SANITIZER_LINUX
181
+ // Perhaps ASLR entropy is too high. If ASLR is enabled, re-exec without it.
182
+ int old_personality = personality (0xffffffff );
183
+ bool aslr_on =
184
+ (old_personality != -1 ) && ((old_personality & ADDR_NO_RANDOMIZE) == 0 );
185
+
186
+ if (aslr_on) {
187
+ VReport (1 ,
188
+ " WARNING: MemorySanitizer: memory layout is incompatible, "
189
+ " possibly due to high-entropy ASLR.\n "
190
+ " Re-execing with fixed virtual address space.\n "
191
+ " N.B. reducing ASLR entropy is preferable.\n " );
192
+ CHECK_NE (personality (old_personality | ADDR_NO_RANDOMIZE), -1 );
193
+ ReExec ();
194
+ }
195
+ # endif
196
+ }
197
+
198
+ // The earlier dry run didn't actually map or protect anything. Run again in
199
+ // non-dry run mode.
200
+ return success && InitShadow (__msan_get_track_origins (), false );
201
+ }
202
+
167
203
static void MsanAtExit (void ) {
168
204
if (flags ()->print_stats && (flags ()->atexit || msan_report_count > 0 ))
169
205
ReportStats ();
0 commit comments