33
33
#include " sanitizer_common/sanitizer_libc.h"
34
34
#include " sanitizer_common/sanitizer_report_decorator.h"
35
35
#include " sanitizer_common/sanitizer_stacktrace.h"
36
+ #if SANITIZER_LINUX
37
+ # include < sys/personality.h>
38
+ #endif
36
39
37
40
using namespace __dfsan ;
38
41
@@ -1127,11 +1130,12 @@ static void CheckMemoryLayoutSanity() {
1127
1130
1128
1131
// TODO: CheckMemoryRangeAvailability is based on msan.
1129
1132
// 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 ) {
1131
1134
if (size > 0 ) {
1132
1135
uptr end = beg + size - 1 ;
1133
1136
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);
1135
1139
return false ;
1136
1140
}
1137
1141
}
@@ -1163,7 +1167,7 @@ static bool ProtectMemoryRange(uptr beg, uptr size, const char *name) {
1163
1167
1164
1168
// TODO: InitShadow is based on msan.
1165
1169
// Consider refactoring these into a shared implementation.
1166
- bool InitShadow (bool init_origins) {
1170
+ bool InitShadow (bool init_origins, bool dry_run ) {
1167
1171
// Let user know mapping parameters first.
1168
1172
VPrintf (1 , " dfsan_init %p\n " , (void *)&__dfsan::dfsan_init);
1169
1173
for (unsigned i = 0 ; i < kMemoryLayoutSize ; ++i)
@@ -1173,8 +1177,9 @@ bool InitShadow(bool init_origins) {
1173
1177
CheckMemoryLayoutSanity ();
1174
1178
1175
1179
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);
1178
1183
return false ;
1179
1184
}
1180
1185
@@ -1195,27 +1200,62 @@ bool InitShadow(bool init_origins) {
1195
1200
bool protect = type == MappingDesc::INVALID ||
1196
1201
(!init_origins && type == MappingDesc::ORIGIN);
1197
1202
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
+ }
1200
1210
if (map) {
1201
- if (!CheckMemoryRangeAvailability (start, size))
1211
+ if (dry_run && !CheckMemoryRangeAvailability (start, size, !dry_run ))
1202
1212
return false ;
1203
- if (!MmapFixedSuperNoReserve (start, size, kMemoryLayout [i].name ))
1213
+ if (!dry_run &&
1214
+ !MmapFixedSuperNoReserve (start, size, kMemoryLayout [i].name ))
1204
1215
return false ;
1205
- if (common_flags ()->use_madv_dontdump )
1216
+ if (!dry_run && common_flags ()->use_madv_dontdump )
1206
1217
DontDumpShadowMemory (start, size);
1207
1218
}
1208
1219
if (protect) {
1209
- if (!CheckMemoryRangeAvailability (start, size))
1220
+ if (dry_run && !CheckMemoryRangeAvailability (start, size, !dry_run ))
1210
1221
return false ;
1211
- if (!ProtectMemoryRange (start, size, kMemoryLayout [i].name ))
1222
+ if (!dry_run && ! ProtectMemoryRange (start, size, kMemoryLayout [i].name ))
1212
1223
return false ;
1213
1224
}
1214
1225
}
1215
1226
1216
1227
return true ;
1217
1228
}
1218
1229
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
+
1219
1259
static void DFsanInit (int argc, char **argv, char **envp) {
1220
1260
CHECK (!dfsan_init_is_running);
1221
1261
if (dfsan_inited)
@@ -1229,7 +1269,11 @@ static void DFsanInit(int argc, char **argv, char **envp) {
1229
1269
1230
1270
CheckASLR ();
1231
1271
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
+ }
1233
1277
1234
1278
initialize_interceptors ();
1235
1279
0 commit comments