3333#include " sanitizer_common/sanitizer_libc.h"
3434#include " sanitizer_common/sanitizer_report_decorator.h"
3535#include " sanitizer_common/sanitizer_stacktrace.h"
36+ #if SANITIZER_LINUX
37+ # include < sys/personality.h>
38+ #endif
3639
3740using namespace __dfsan ;
3841
@@ -1127,11 +1130,12 @@ static void CheckMemoryLayoutSanity() {
11271130
11281131// TODO: CheckMemoryRangeAvailability is based on msan.
11291132// Consider refactoring these into a shared implementation.
1130- static bool CheckMemoryRangeAvailability (uptr beg, uptr size) {
1133+ static bool CheckMemoryRangeAvailability (uptr beg, uptr size, bool verbose ) {
11311134 if (size > 0 ) {
11321135 uptr end = beg + size - 1 ;
11331136 if (!MemoryRangeIsAvailable (beg, end)) {
1134- Printf (" FATAL: Memory range %p - %p is not available.\n " , beg, end);
1137+ if (verbose)
1138+ Printf (" FATAL: Memory range %p - %p is not available.\n " , beg, end);
11351139 return false ;
11361140 }
11371141 }
@@ -1163,7 +1167,7 @@ static bool ProtectMemoryRange(uptr beg, uptr size, const char *name) {
11631167
11641168// TODO: InitShadow is based on msan.
11651169// Consider refactoring these into a shared implementation.
1166- bool InitShadow (bool init_origins) {
1170+ bool InitShadow (bool init_origins, bool dry_run ) {
11671171 // Let user know mapping parameters first.
11681172 VPrintf (1 , " dfsan_init %p\n " , (void *)&__dfsan::dfsan_init);
11691173 for (unsigned i = 0 ; i < kMemoryLayoutSize ; ++i)
@@ -1173,8 +1177,9 @@ bool InitShadow(bool init_origins) {
11731177 CheckMemoryLayoutSanity ();
11741178
11751179 if (!MEM_IS_APP (&__dfsan::dfsan_init)) {
1176- Printf (" FATAL: Code %p is out of application range. Non-PIE build?\n " ,
1177- (uptr)&__dfsan::dfsan_init);
1180+ if (!dry_run)
1181+ Printf (" FATAL: Code %p is out of application range. Non-PIE build?\n " ,
1182+ (uptr)&__dfsan::dfsan_init);
11781183 return false ;
11791184 }
11801185
@@ -1195,27 +1200,62 @@ bool InitShadow(bool init_origins) {
11951200 bool protect = type == MappingDesc::INVALID ||
11961201 (!init_origins && type == MappingDesc::ORIGIN);
11971202 CHECK (!(map && protect));
1198- if (!map && !protect)
1199- CHECK (type == MappingDesc::APP);
1203+ if (!map && !protect) {
1204+ CHECK (type == MappingDesc::APP || type == MappingDesc::ALLOCATOR);
1205+
1206+ if (dry_run && type == MappingDesc::ALLOCATOR &&
1207+ !CheckMemoryRangeAvailability (start, size, !dry_run))
1208+ return false ;
1209+ }
12001210 if (map) {
1201- if (!CheckMemoryRangeAvailability (start, size))
1211+ if (dry_run && !CheckMemoryRangeAvailability (start, size, !dry_run ))
12021212 return false ;
1203- if (!MmapFixedSuperNoReserve (start, size, kMemoryLayout [i].name ))
1213+ if (!dry_run &&
1214+ !MmapFixedSuperNoReserve (start, size, kMemoryLayout [i].name ))
12041215 return false ;
1205- if (common_flags ()->use_madv_dontdump )
1216+ if (!dry_run && common_flags ()->use_madv_dontdump )
12061217 DontDumpShadowMemory (start, size);
12071218 }
12081219 if (protect) {
1209- if (!CheckMemoryRangeAvailability (start, size))
1220+ if (dry_run && !CheckMemoryRangeAvailability (start, size, !dry_run ))
12101221 return false ;
1211- if (!ProtectMemoryRange (start, size, kMemoryLayout [i].name ))
1222+ if (!dry_run && ! ProtectMemoryRange (start, size, kMemoryLayout [i].name ))
12121223 return false ;
12131224 }
12141225 }
12151226
12161227 return true ;
12171228}
12181229
1230+ bool InitShadowWithReExec (bool init_origins) {
1231+ // Start with dry run: check layout is ok, but don't print warnings because
1232+ // warning messages will cause tests to fail (even if we successfully re-exec
1233+ // after the warning).
1234+ bool success = InitShadow (init_origins, true );
1235+ if (!success) {
1236+ #if SANITIZER_LINUX
1237+ // Perhaps ASLR entropy is too high. If ASLR is enabled, re-exec without it.
1238+ int old_personality = personality (0xffffffff );
1239+ bool aslr_on =
1240+ (old_personality != -1 ) && ((old_personality & ADDR_NO_RANDOMIZE) == 0 );
1241+
1242+ if (aslr_on) {
1243+ VReport (1 ,
1244+ " WARNING: DataflowSanitizer: memory layout is incompatible, "
1245+ " possibly due to high-entropy ASLR.\n "
1246+ " Re-execing with fixed virtual address space.\n "
1247+ " N.B. reducing ASLR entropy is preferable.\n " );
1248+ CHECK_NE (personality (old_personality | ADDR_NO_RANDOMIZE), -1 );
1249+ ReExec ();
1250+ }
1251+ #endif
1252+ }
1253+
1254+ // The earlier dry run didn't actually map or protect anything. Run again in
1255+ // non-dry run mode.
1256+ return success && InitShadow (init_origins, false );
1257+ }
1258+
12191259static void DFsanInit (int argc, char **argv, char **envp) {
12201260 CHECK (!dfsan_init_is_running);
12211261 if (dfsan_inited)
@@ -1229,7 +1269,11 @@ static void DFsanInit(int argc, char **argv, char **envp) {
12291269
12301270 CheckASLR ();
12311271
1232- InitShadow (dfsan_get_track_origins ());
1272+ if (!InitShadowWithReExec (dfsan_get_track_origins ())) {
1273+ Printf (" FATAL: DataflowSanitizer can not mmap the shadow memory.\n " );
1274+ DumpProcessMap ();
1275+ Die ();
1276+ }
12331277
12341278 initialize_interceptors ();
12351279
0 commit comments