2020# include < signal.h>
2121# include < stdio.h>
2222# include < stdlib.h>
23+ # if SANITIZER_LINUX
24+ # include < sys/personality.h>
25+ # endif
2326# include < sys/resource.h>
2427# include < sys/time.h>
2528# include < unistd.h>
@@ -43,11 +46,13 @@ void ReportMapRange(const char *descr, uptr beg, uptr size) {
4346 }
4447}
4548
46- static bool CheckMemoryRangeAvailability (uptr beg, uptr size) {
49+ static bool CheckMemoryRangeAvailability (uptr beg, uptr size, bool verbose ) {
4750 if (size > 0 ) {
4851 uptr end = beg + size - 1 ;
4952 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);
5156 return false ;
5257 }
5358 }
@@ -106,7 +111,7 @@ static void CheckMemoryLayoutSanity() {
106111 }
107112}
108113
109- bool InitShadow (bool init_origins) {
114+ static bool InitShadow (bool init_origins, bool dry_run ) {
110115 // Let user know mapping parameters first.
111116 VPrintf (1 , " __msan_init %p\n " , reinterpret_cast <void *>(&__msan_init));
112117 for (unsigned i = 0 ; i < kMemoryLayoutSize ; ++i)
@@ -116,8 +121,9 @@ bool InitShadow(bool init_origins) {
116121 CheckMemoryLayoutSanity ();
117122
118123 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));
121127 return false ;
122128 }
123129
@@ -142,28 +148,60 @@ bool InitShadow(bool init_origins) {
142148 CHECK (type == MappingDesc::APP || type == MappingDesc::ALLOCATOR);
143149
144150 if (type == MappingDesc::ALLOCATOR &&
145- !CheckMemoryRangeAvailability (start, size))
151+ !CheckMemoryRangeAvailability (start, size, !dry_run ))
146152 return false ;
147153 }
148154 if (map) {
149- if (!CheckMemoryRangeAvailability (start, size))
155+ if (!CheckMemoryRangeAvailability (start, size, !dry_run ))
150156 return false ;
151- if (!MmapFixedSuperNoReserve (start, size, kMemoryLayout [i].name ))
157+ if (!dry_run &&
158+ !MmapFixedSuperNoReserve (start, size, kMemoryLayout [i].name ))
152159 return false ;
153- if (common_flags ()->use_madv_dontdump )
160+ if (!dry_run && common_flags ()->use_madv_dontdump )
154161 DontDumpShadowMemory (start, size);
155162 }
156163 if (protect) {
157- if (!CheckMemoryRangeAvailability (start, size))
164+ if (!CheckMemoryRangeAvailability (start, size, !dry_run ))
158165 return false ;
159- if (!ProtectMemoryRange (start, size, kMemoryLayout [i].name ))
166+ if (!dry_run && ! ProtectMemoryRange (start, size, kMemoryLayout [i].name ))
160167 return false ;
161168 }
162169 }
163170
164171 return true ;
165172}
166173
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+ success = InitShadow (__msan_get_track_origins (), false );
201+
202+ return success;
203+ }
204+
167205static void MsanAtExit (void ) {
168206 if (flags ()->print_stats && (flags ()->atexit || msan_report_count > 0 ))
169207 ReportStats ();
0 commit comments