OLD | NEW |
1 // Copyright 2012 Google Inc. All Rights Reserved. | 1 // Copyright 2012 Google Inc. All Rights Reserved. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 | 60 |
61 namespace agent { | 61 namespace agent { |
62 namespace asan { | 62 namespace asan { |
63 | 63 |
64 namespace { | 64 namespace { |
65 | 65 |
66 using agent::asan::AsanLogger; | 66 using agent::asan::AsanLogger; |
67 using agent::asan::StackCaptureCache; | 67 using agent::asan::StackCaptureCache; |
68 using agent::asan::WindowsHeapAdapter; | 68 using agent::asan::WindowsHeapAdapter; |
69 | 69 |
| 70 enum CrashReporterType { |
| 71 kDefaultCrashReporterType, |
| 72 kBreakpadCrashReporterType, |
| 73 kKaskoCrashReporterType, |
| 74 kCrashpadCrashReporterType, |
| 75 }; |
| 76 |
70 // A custom exception code we use to indicate that the exception originated | 77 // A custom exception code we use to indicate that the exception originated |
71 // from Asan, and shouldn't be processed again by our unhandled exception | 78 // from Asan, and shouldn't be processed again by our unhandled exception |
72 // handler. This value has been created according to the rules here: | 79 // handler. This value has been created according to the rules here: |
73 // http://msdn.microsoft.com/en-us/library/windows/hardware/ff543026(v=vs.85).as
px | 80 // http://msdn.microsoft.com/en-us/library/windows/hardware/ff543026(v=vs.85).as
px |
74 // See winerror.h for more details. | 81 // See winerror.h for more details. |
75 static const DWORD kAsanFacility = 0x68B; // No more than 11 bits. | 82 static const DWORD kAsanFacility = 0x68B; // No more than 11 bits. |
76 static const DWORD kAsanStatus = 0x5AD0; // No more than 16 bits. | 83 static const DWORD kAsanStatus = 0x5AD0; // No more than 16 bits. |
77 static const DWORD kAsanException = | 84 static const DWORD kAsanException = |
78 (3 << 30) | // Severity = error. | 85 (3 << 30) | // Severity = error. |
79 (1 << 29) | // Customer defined code (not defined by MS). | 86 (1 << 29) | // Customer defined code (not defined by MS). |
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 ->WriteCorruptHeapInfo(corrupt_ranges, size, buffer, error_info); \ | 387 ->WriteCorruptHeapInfo(corrupt_ranges, size, buffer, error_info); \ |
381 } \ | 388 } \ |
382 } | 389 } |
383 | 390 |
384 void LaunchMessageBox(const base::StringPiece& message) { | 391 void LaunchMessageBox(const base::StringPiece& message) { |
385 // TODO(chrisha): Consider making this close itself with a timeout to prevent | 392 // TODO(chrisha): Consider making this close itself with a timeout to prevent |
386 // hangs on the waterfall. | 393 // hangs on the waterfall. |
387 ::MessageBoxA(nullptr, message.data(), nullptr, MB_OK | MB_ICONEXCLAMATION); | 394 ::MessageBoxA(nullptr, message.data(), nullptr, MB_OK | MB_ICONEXCLAMATION); |
388 } | 395 } |
389 | 396 |
390 std::unique_ptr<ReporterInterface> CreateCrashReporter(AsanLogger* logger) { | 397 // Gets the preferred crash reporter type from the environment. This will |
| 398 // override experiments or command-lines, and is largely meant for local |
| 399 // testing. |
| 400 CrashReporterType GetCrashReporterTypeFromEnvironment( |
| 401 AsanLogger* logger) { |
| 402 DCHECK_NE(static_cast<AsanLogger*>(nullptr), logger); |
391 std::unique_ptr<ReporterInterface> reporter; | 403 std::unique_ptr<ReporterInterface> reporter; |
392 | 404 |
393 // First try to grab the preferred crash reporter, overridden by the | |
394 // environment. | |
395 std::unique_ptr<base::Environment> env(base::Environment::Create()); | 405 std::unique_ptr<base::Environment> env(base::Environment::Create()); |
396 std::string reporter_name; | 406 std::string reporter_name; |
397 if (env->GetVar("SYZYASAN_CRASH_REPORTER", &reporter_name)) { | 407 static const char kSyzyAsanCrashReporterEnv[] = |
398 if (reporter_name == "crashpad") | 408 "SYZYASAN_CRASH_REPORTER"; |
399 reporter.reset(reporters::CrashpadReporter::Create().release()); | 409 if (!env->GetVar(kSyzyAsanCrashReporterEnv, &reporter_name)) |
400 else if (reporter_name == "kasko") | 410 return kDefaultCrashReporterType; |
401 reporter.reset(reporters::KaskoReporter::Create().release()); | |
402 else if (reporter_name == "breakpad") | |
403 reporter.reset(reporters::BreakpadReporter::Create().release()); | |
404 | 411 |
405 if (reporter.get() != nullptr) { | 412 CrashReporterType type = kDefaultCrashReporterType; |
406 logger->Write(base::StringPrintf( | 413 if (reporter_name == "crashpad") { |
407 "Using requested \"%s\" crash reporter.", reporter_name)); | 414 type = kCrashpadCrashReporterType; |
408 return reporter; | 415 } else if (reporter_name == "kasko") { |
409 } else { | 416 type = kKaskoCrashReporterType; |
410 logger->Write(base::StringPrintf( | 417 } else if (reporter_name == "breakpad") { |
411 "Unable to create requested \"%s\" crash reporter.", reporter_name)); | 418 type = kBreakpadCrashReporterType; |
412 } | |
413 } | 419 } |
414 | 420 |
415 // No crash reporter was explicitly specified, or it was unable to be | 421 if (type != kDefaultCrashReporterType) { |
416 // initialized. Try all of them, starting with the most recent. | 422 logger->Write(base::StringPrintf("Encountered %s=\"%s\".", |
| 423 kSyzyAsanCrashReporterEnv, reporter_name.c_str())); |
| 424 } else { |
| 425 logger->Write(base::StringPrintf("Ignoring %s=\"%s\".", |
| 426 kSyzyAsanCrashReporterEnv, reporter_name.c_str())); |
| 427 } |
417 | 428 |
418 // Don't try grabbing a Crashpad reporter by default, as we're not yet | 429 return type; |
419 // ready to ship this. | 430 } |
420 // TODO(chrisha): Add Crashpad support behind a feature flag. | 431 |
| 432 // Attempts to create a crash reporter, starting with the most modern. |
| 433 std::unique_ptr<ReporterInterface> CreateCrashReporterWithTypeHint( |
| 434 AsanLogger* logger, CrashReporterType reporter_type) { |
| 435 std::unique_ptr<ReporterInterface> reporter; |
| 436 |
| 437 // Crashpad is not yet enabled by default. |
| 438 if (reporter_type == kCrashpadCrashReporterType) |
| 439 reporter.reset(reporters::CrashpadReporter::Create().release()); |
421 | 440 |
422 // Try to initialize a Kasko crash reporter. | 441 // Try to initialize a Kasko crash reporter. |
423 if (reporter.get() == nullptr) | 442 if (reporter.get() == nullptr && |
| 443 (reporter_type == kKaskoCrashReporterType || |
| 444 reporter_type == kDefaultCrashReporterType)) { |
424 reporter.reset(reporters::KaskoReporter::Create().release()); | 445 reporter.reset(reporters::KaskoReporter::Create().release()); |
| 446 } |
425 | 447 |
426 // If that failed then try to initialize a Breakpad reporter. | 448 // If that failed then try to initialize a Breakpad reporter. |
427 if (reporter.get() == nullptr) | 449 if (reporter.get() == nullptr && |
| 450 (reporter_type == kBreakpadCrashReporterType || |
| 451 reporter_type == kDefaultCrashReporterType)) { |
428 reporter.reset(reporters::BreakpadReporter::Create().release()); | 452 reporter.reset(reporters::BreakpadReporter::Create().release()); |
| 453 } |
429 | 454 |
430 return reporter; | 455 return reporter; |
431 } | 456 } |
432 | 457 |
433 } // namespace | 458 } // namespace |
434 | 459 |
435 base::Lock AsanRuntime::lock_; | 460 base::Lock AsanRuntime::lock_; |
436 AsanRuntime* AsanRuntime::runtime_ = NULL; | 461 AsanRuntime* AsanRuntime::runtime_ = NULL; |
437 LPTOP_LEVEL_EXCEPTION_FILTER AsanRuntime::previous_uef_ = NULL; | 462 LPTOP_LEVEL_EXCEPTION_FILTER AsanRuntime::previous_uef_ = NULL; |
438 bool AsanRuntime::uef_installed_ = false; | 463 bool AsanRuntime::uef_installed_ = false; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
476 if (!SetUpMemoryNotifier()) | 501 if (!SetUpMemoryNotifier()) |
477 return false; | 502 return false; |
478 if (!SetUpLogger()) | 503 if (!SetUpLogger()) |
479 return false; | 504 return false; |
480 if (!SetUpStackCache()) | 505 if (!SetUpStackCache()) |
481 return false; | 506 return false; |
482 if (!SetUpHeapManager()) | 507 if (!SetUpHeapManager()) |
483 return false; | 508 return false; |
484 WindowsHeapAdapter::SetUp(heap_manager_.get()); | 509 WindowsHeapAdapter::SetUp(heap_manager_.get()); |
485 | 510 |
| 511 // Determine the preferred crash reporter type, as specified in the |
| 512 // environment. If this isn't present it defaults to |
| 513 // kDefaultCrashReporterType, in which case experiments or command-line flags |
| 514 // may specify the crash reporter to use. |
| 515 CrashReporterType crash_reporter_type = |
| 516 GetCrashReporterTypeFromEnvironment(logger()); |
| 517 |
486 if (params_.feature_randomization) { | 518 if (params_.feature_randomization) { |
487 AsanFeatureSet feature_set = GenerateRandomFeatureSet(); | 519 AsanFeatureSet feature_set = GenerateRandomFeatureSet(); |
488 PropagateFeatureSet(feature_set); | 520 PropagateFeatureSet(feature_set); |
| 521 |
| 522 // If no specific crash reporter has been specified, then allow the |
| 523 // experiment to specify it. |
| 524 if (crash_reporter_type == kDefaultCrashReporterType && |
| 525 (feature_set & ASAN_FEATURE_ENABLE_CRASHPAD) != 0) { |
| 526 crash_reporter_type = kCrashpadCrashReporterType; |
| 527 } |
489 } | 528 } |
490 | 529 |
491 // Propagates the flags values to the different modules. | 530 // Propagates the flags values to the different modules. |
492 PropagateParams(); | 531 PropagateParams(); |
493 | 532 |
494 // The name 'disable_breakpad_reporting' is legacy; this actually means to | 533 // The name 'disable_breakpad_reporting' is legacy; this actually means to |
495 // disable all external crash reporting integration. | 534 // disable all external crash reporting integration. |
496 if (!params_.disable_breakpad_reporting) | 535 if (!params_.disable_breakpad_reporting) { |
497 crash_reporter_.reset(CreateCrashReporter(logger()).release()); | 536 // This will create the crash reporter with a preference for creating a |
| 537 // reporter of the hinted type. If such a reporter isn't available, it will |
| 538 // fall back to trying to create the most 'modern' reporter available. |
| 539 crash_reporter_.reset(CreateCrashReporterWithTypeHint( |
| 540 logger(), crash_reporter_type).release()); |
| 541 } |
498 | 542 |
499 // Set up the appropriate error handler depending on whether or not | 543 // Set up the appropriate error handler depending on whether or not |
500 // we successfully found a crash reporter. | 544 // we successfully initialized a crash reporter. |
501 if (crash_reporter_.get() != nullptr) { | 545 if (crash_reporter_.get() != nullptr) { |
502 logger_->Write(base::StringPrintf( | 546 logger_->Write(base::StringPrintf( |
503 "SyzyASAN: Using %s for error reporting.", | 547 "SyzyASAN: Using %s for error reporting.", |
504 crash_reporter_->GetName())); | 548 crash_reporter_->GetName())); |
505 SetErrorCallBack(base::Bind(&CrashReporterErrorHandler)); | 549 SetErrorCallBack(base::Bind(&CrashReporterErrorHandler)); |
506 } else { | 550 } else { |
507 logger_->Write("SyzyASAN: Using default error reporting handler."); | 551 logger_->Write("SyzyASAN: Using default error reporting handler."); |
508 SetErrorCallBack(base::Bind(&DefaultErrorHandler)); | 552 SetErrorCallBack(base::Bind(&DefaultErrorHandler)); |
509 } | 553 } |
510 | 554 |
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
954 } | 998 } |
955 | 999 |
956 // Print the Windbg information to display the free stack if present. | 1000 // Print the Windbg information to display the free stack if present. |
957 if (error_info->block_info.free_stack_size != NULL) { | 1001 if (error_info->block_info.free_stack_size != NULL) { |
958 AsanDbgMessage(L"Free stack trace:"); | 1002 AsanDbgMessage(L"Free stack trace:"); |
959 AsanDbgCmd(L"dps %p l%d", error_info->block_info.free_stack, | 1003 AsanDbgCmd(L"dps %p l%d", error_info->block_info.free_stack, |
960 error_info->block_info.free_stack_size); | 1004 error_info->block_info.free_stack_size); |
961 } | 1005 } |
962 } | 1006 } |
963 | 1007 |
| 1008 // static |
964 AsanFeatureSet AsanRuntime::GenerateRandomFeatureSet() { | 1009 AsanFeatureSet AsanRuntime::GenerateRandomFeatureSet() { |
965 AsanFeatureSet enabled_features = | 1010 AsanFeatureSet enabled_features = |
966 static_cast<AsanFeatureSet>(base::RandGenerator(ASAN_FEATURE_MAX)); | 1011 static_cast<AsanFeatureSet>(base::RandGenerator(ASAN_FEATURE_MAX)); |
967 DCHECK_LT(enabled_features, ASAN_FEATURE_MAX); | 1012 DCHECK_LT(enabled_features, ASAN_FEATURE_MAX); |
968 enabled_features &= kAsanValidFeatures; | 1013 enabled_features &= kAsanValidFeatures; |
969 return enabled_features; | 1014 return enabled_features; |
970 } | 1015 } |
971 | 1016 |
972 void AsanRuntime::PropagateFeatureSet(AsanFeatureSet feature_set) { | 1017 void AsanRuntime::PropagateFeatureSet(AsanFeatureSet feature_set) { |
973 DCHECK_EQ(0U, feature_set & ~kAsanValidFeatures); | 1018 DCHECK_EQ(0U, feature_set & ~kAsanValidFeatures); |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1192 DCHECK(heap_manager_); | 1237 DCHECK(heap_manager_); |
1193 heap_manager_->DisableDeferredFreeThread(); | 1238 heap_manager_->DisableDeferredFreeThread(); |
1194 } | 1239 } |
1195 | 1240 |
1196 AsanFeatureSet AsanRuntime::GetEnabledFeatureSet() { | 1241 AsanFeatureSet AsanRuntime::GetEnabledFeatureSet() { |
1197 AsanFeatureSet enabled_features = static_cast<AsanFeatureSet>(0U); | 1242 AsanFeatureSet enabled_features = static_cast<AsanFeatureSet>(0U); |
1198 if (heap_manager_->enable_page_protections_) | 1243 if (heap_manager_->enable_page_protections_) |
1199 enabled_features |= ASAN_FEATURE_ENABLE_PAGE_PROTECTIONS; | 1244 enabled_features |= ASAN_FEATURE_ENABLE_PAGE_PROTECTIONS; |
1200 if (params_.enable_large_block_heap) | 1245 if (params_.enable_large_block_heap) |
1201 enabled_features |= ASAN_FEATURE_ENABLE_LARGE_BLOCK_HEAP; | 1246 enabled_features |= ASAN_FEATURE_ENABLE_LARGE_BLOCK_HEAP; |
| 1247 if (crash_reporter_.get() != nullptr && |
| 1248 crash_reporter_->GetName() == reporters::CrashpadReporter::kName) { |
| 1249 enabled_features |= ASAN_FEATURE_ENABLE_CRASHPAD; |
| 1250 } |
1202 | 1251 |
1203 return enabled_features; | 1252 return enabled_features; |
1204 } | 1253 } |
1205 | 1254 |
1206 } // namespace asan | 1255 } // namespace asan |
1207 } // namespace agent | 1256 } // namespace agent |
OLD | NEW |