From e467c59c689d176ad0f311935022ed18110748fb Mon Sep 17 00:00:00 2001 From: Alex Gough Date: Tue, 19 Jul 2022 05:23:55 -0700 Subject: [PATCH] Adds fastfail subcodes as distinct failure reasons Previously these all resulted in EXCEPTION_STACK_BUFFER_OVERRUN but this hides various specific fast fail crash types, which are now provided based on the exception's subcode. Tests: added to minidump_process_unittest.cc Bug: 865632 Change-Id: Ic6693de247da55cf6d132d108c6e20c635f366b1 Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/3771437 Reviewed-by: Robert Sesek --- .../common/minidump_exception_win32.h | 73 ++++++ src/processor/minidump_processor.cc | 215 +++++++++++++++++- src/processor/minidump_processor_unittest.cc | 16 ++ src/processor/testdata/tiny-exe-fastfail.dmp | Bin 0 -> 98722 bytes 4 files changed, 303 insertions(+), 1 deletion(-) create mode 100644 src/processor/testdata/tiny-exe-fastfail.dmp diff --git a/src/google_breakpad/common/minidump_exception_win32.h b/src/google_breakpad/common/minidump_exception_win32.h index 4b5d57c8..9f734d5b 100644 --- a/src/google_breakpad/common/minidump_exception_win32.h +++ b/src/google_breakpad/common/minidump_exception_win32.h @@ -2266,4 +2266,77 @@ typedef enum { MD_IN_PAGE_ERROR_WIN_EXEC = 8 } MDInPageErrorTypeWin; +// These constants are defined in winnt.h and are used with the +// STATUS_STACK_BUFFER_OVERRUN exception as exception subcodes. +typedef enum { + MD_FAST_FAIL_LEGACY_GS_VIOLATION = 0, + MD_FAST_FAIL_VTGUARD_CHECK_FAILURE = 1, + MD_FAST_FAIL_STACK_COOKIE_CHECK_FAILURE = 2, + MD_FAST_FAIL_CORRUPT_LIST_ENTRY = 3, + MD_FAST_FAIL_INCORRECT_STACK = 4, + MD_FAST_FAIL_INVALID_ARG = 5, + MD_FAST_FAIL_GS_COOKIE_INIT = 6, + MD_FAST_FAIL_FATAL_APP_EXIT = 7, + MD_FAST_FAIL_RANGE_CHECK_FAILURE = 8, + MD_FAST_FAIL_UNSAFE_REGISTRY_ACCESS = 9, + MD_FAST_FAIL_GUARD_ICALL_CHECK_FAILURE = 10, + MD_FAST_FAIL_GUARD_WRITE_CHECK_FAILURE = 11, + MD_FAST_FAIL_INVALID_FIBER_SWITCH = 12, + MD_FAST_FAIL_INVALID_SET_OF_CONTEXT = 13, + MD_FAST_FAIL_INVALID_REFERENCE_COUNT = 14, + MD_FAST_FAIL_INVALID_JUMP_BUFFER = 18, + MD_FAST_FAIL_MRDATA_MODIFIED = 19, + MD_FAST_FAIL_CERTIFICATION_FAILURE = 20, + MD_FAST_FAIL_INVALID_EXCEPTION_CHAIN = 21, + MD_FAST_FAIL_CRYPTO_LIBRARY = 22, + MD_FAST_FAIL_INVALID_CALL_IN_DLL_CALLOUT = 23, + MD_FAST_FAIL_INVALID_IMAGE_BASE = 24, + MD_FAST_FAIL_DLOAD_PROTECTION_FAILURE = 25, + MD_FAST_FAIL_UNSAFE_EXTENSION_CALL = 26, + MD_FAST_FAIL_DEPRECATED_SERVICE_INVOKED = 27, + MD_FAST_FAIL_INVALID_BUFFER_ACCESS = 28, + MD_FAST_FAIL_INVALID_BALANCED_TREE = 29, + MD_FAST_FAIL_INVALID_NEXT_THREAD = 30, + MD_FAST_FAIL_GUARD_ICALL_CHECK_SUPPRESSED = 31, + MD_FAST_FAIL_APCS_DISABLED = 32, + MD_FAST_FAIL_INVALID_IDLE_STATE = 33, + MD_FAST_FAIL_MRDATA_PROTECTION_FAILURE = 34, + MD_FAST_FAIL_UNEXPECTED_HEAP_EXCEPTION = 35, + MD_FAST_FAIL_INVALID_LOCK_STATE = 36, + MD_FAST_FAIL_GUARD_JUMPTABLE = 37, + MD_FAST_FAIL_INVALID_LONGJUMP_TARGET = 38, + MD_FAST_FAIL_INVALID_DISPATCH_CONTEXT = 39, + MD_FAST_FAIL_INVALID_THREAD = 40, + MD_FAST_FAIL_INVALID_SYSCALL_NUMBER = 41, + MD_FAST_FAIL_INVALID_FILE_OPERATION = 42, + MD_FAST_FAIL_LPAC_ACCESS_DENIED = 43, + MD_FAST_FAIL_GUARD_SS_FAILURE = 44, + MD_FAST_FAIL_LOADER_CONTINUITY_FAILURE = 45, + MD_FAST_FAIL_GUARD_EXPORT_SUPPRESSION_FAILURE = 46, + MD_FAST_FAIL_INVALID_CONTROL_STACK = 47, + MD_FAST_FAIL_SET_CONTEXT_DENIED = 48, + MD_FAST_FAIL_INVALID_IAT = 49, + MD_FAST_FAIL_HEAP_METADATA_CORRUPTION = 50, + MD_FAST_FAIL_PAYLOAD_RESTRICTION_VIOLATION = 51, + MD_FAST_FAIL_LOW_LABEL_ACCESS_DENIED = 52, + MD_FAST_FAIL_ENCLAVE_CALL_FAILURE = 53, + MD_FAST_FAIL_UNHANDLED_LSS_EXCEPTON = 54, + MD_FAST_FAIL_ADMINLESS_ACCESS_DENIED = 55, + MD_FAST_FAIL_UNEXPECTED_CALL = 56, + MD_FAST_FAIL_CONTROL_INVALID_RETURN_ADDRESS = 57, + MD_FAST_FAIL_UNEXPECTED_HOST_BEHAVIOR = 58, + MD_FAST_FAIL_FLAGS_CORRUPTION = 59, + MD_FAST_FAIL_VEH_CORRUPTION = 60, + MD_FAST_FAIL_ETW_CORRUPTION = 61, + MD_FAST_FAIL_RIO_ABORT = 62, + MD_FAST_FAIL_INVALID_PFN = 63, + MD_FAST_FAIL_GUARD_ICALL_CHECK_FAILURE_XFG = 64, + MD_FAST_FAIL_CAST_GUARD = 65, + MD_FAST_FAIL_HOST_VISIBILITY_CHANGE = 66, + MD_FAST_FAIL_KERNEL_CET_SHADOW_STACK_ASSIST = 67, + MD_FAST_FAIL_PATCH_CALLBACK_FAILED = 68, + MD_FAST_FAIL_NTDLL_PATCH_FAILED = 69, + MD_FAST_FAIL_INVALID_FLS_DATA = 70 +} MDFastFailSubcodeTypeWin; + #endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_WIN32_H__ */ diff --git a/src/processor/minidump_processor.cc b/src/processor/minidump_processor.cc index fd4b28e2..e6875c9e 100644 --- a/src/processor/minidump_processor.cc +++ b/src/processor/minidump_processor.cc @@ -1330,7 +1330,220 @@ string MinidumpProcessor::GetCrashReason(Minidump* dump, uint64_t* address) { reason = "EXCEPTION_POSSIBLE_DEADLOCK"; break; case MD_EXCEPTION_CODE_WIN_STACK_BUFFER_OVERRUN: - reason = "EXCEPTION_STACK_BUFFER_OVERRUN"; + if (raw_exception->exception_record.number_parameters >= 1) { + MDFastFailSubcodeTypeWin subcode = + static_cast( + raw_exception->exception_record.exception_information[0]); + switch (subcode) { + // Note - we skip the '0'/GS case as it exists for legacy reasons. + case MD_FAST_FAIL_VTGUARD_CHECK_FAILURE: + reason = "FAST_FAIL_VTGUARD_CHECK_FAILURE"; + break; + case MD_FAST_FAIL_STACK_COOKIE_CHECK_FAILURE: + reason = "FAST_FAIL_STACK_COOKIE_CHECK_FAILURE"; + break; + case MD_FAST_FAIL_CORRUPT_LIST_ENTRY: + reason = "FAST_FAIL_CORRUPT_LIST_ENTRY"; + break; + case MD_FAST_FAIL_INCORRECT_STACK: + reason = "FAST_FAIL_INCORRECT_STACK"; + break; + case MD_FAST_FAIL_INVALID_ARG: + reason = "FAST_FAIL_INVALID_ARG"; + break; + case MD_FAST_FAIL_GS_COOKIE_INIT: + reason = "FAST_FAIL_GS_COOKIE_INIT"; + break; + case MD_FAST_FAIL_FATAL_APP_EXIT: + reason = "FAST_FAIL_FATAL_APP_EXIT"; + break; + case MD_FAST_FAIL_RANGE_CHECK_FAILURE: + reason = "FAST_FAIL_RANGE_CHECK_FAILURE"; + break; + case MD_FAST_FAIL_UNSAFE_REGISTRY_ACCESS: + reason = "FAST_FAIL_UNSAFE_REGISTRY_ACCESS"; + break; + case MD_FAST_FAIL_GUARD_ICALL_CHECK_FAILURE: + reason = "FAST_FAIL_GUARD_ICALL_CHECK_FAILURE"; + break; + case MD_FAST_FAIL_GUARD_WRITE_CHECK_FAILURE: + reason = "FAST_FAIL_GUARD_WRITE_CHECK_FAILURE"; + break; + case MD_FAST_FAIL_INVALID_FIBER_SWITCH: + reason = "FAST_FAIL_INVALID_FIBER_SWITCH"; + break; + case MD_FAST_FAIL_INVALID_SET_OF_CONTEXT: + reason = "FAST_FAIL_INVALID_SET_OF_CONTEXT"; + break; + case MD_FAST_FAIL_INVALID_REFERENCE_COUNT: + reason = "FAST_FAIL_INVALID_REFERENCE_COUNT"; + break; + case MD_FAST_FAIL_INVALID_JUMP_BUFFER: + reason = "FAST_FAIL_INVALID_JUMP_BUFFER"; + break; + case MD_FAST_FAIL_MRDATA_MODIFIED: + reason = "FAST_FAIL_MRDATA_MODIFIED"; + break; + case MD_FAST_FAIL_CERTIFICATION_FAILURE: + reason = "FAST_FAIL_CERTIFICATION_FAILURE"; + break; + case MD_FAST_FAIL_INVALID_EXCEPTION_CHAIN: + reason = "FAST_FAIL_INVALID_EXCEPTION_CHAIN"; + break; + case MD_FAST_FAIL_CRYPTO_LIBRARY: + reason = "FAST_FAIL_CRYPTO_LIBRARY"; + break; + case MD_FAST_FAIL_INVALID_CALL_IN_DLL_CALLOUT: + reason = "FAST_FAIL_INVALID_CALL_IN_DLL_CALLOUT"; + break; + case MD_FAST_FAIL_INVALID_IMAGE_BASE: + reason = "FAST_FAIL_INVALID_IMAGE_BASE"; + break; + case MD_FAST_FAIL_DLOAD_PROTECTION_FAILURE: + reason = "FAST_FAIL_DLOAD_PROTECTION_FAILURE"; + break; + case MD_FAST_FAIL_UNSAFE_EXTENSION_CALL: + reason = "FAST_FAIL_UNSAFE_EXTENSION_CALL"; + break; + case MD_FAST_FAIL_DEPRECATED_SERVICE_INVOKED: + reason = "FAST_FAIL_DEPRECATED_SERVICE_INVOKED"; + break; + case MD_FAST_FAIL_INVALID_BUFFER_ACCESS: + reason = "FAST_FAIL_INVALID_BUFFER_ACCESS"; + break; + case MD_FAST_FAIL_INVALID_BALANCED_TREE: + reason = "FAST_FAIL_INVALID_BALANCED_TREE"; + break; + case MD_FAST_FAIL_INVALID_NEXT_THREAD: + reason = "FAST_FAIL_INVALID_NEXT_THREAD"; + break; + case MD_FAST_FAIL_GUARD_ICALL_CHECK_SUPPRESSED: + reason = "FAST_FAIL_GUARD_ICALL_CHECK_SUPPRESSED"; + break; + case MD_FAST_FAIL_APCS_DISABLED: + reason = "FAST_FAIL_APCS_DISABLED"; + break; + case MD_FAST_FAIL_INVALID_IDLE_STATE: + reason = "FAST_FAIL_INVALID_IDLE_STATE"; + break; + case MD_FAST_FAIL_MRDATA_PROTECTION_FAILURE: + reason = "FAST_FAIL_MRDATA_PROTECTION_FAILURE"; + break; + case MD_FAST_FAIL_UNEXPECTED_HEAP_EXCEPTION: + reason = "FAST_FAIL_UNEXPECTED_HEAP_EXCEPTION"; + break; + case MD_FAST_FAIL_INVALID_LOCK_STATE: + reason = "FAST_FAIL_INVALID_LOCK_STATE"; + break; + case MD_FAST_FAIL_GUARD_JUMPTABLE: + reason = "FAST_FAIL_GUARD_JUMPTABLE"; + break; + case MD_FAST_FAIL_INVALID_LONGJUMP_TARGET: + reason = "FAST_FAIL_INVALID_LONGJUMP_TARGET"; + break; + case MD_FAST_FAIL_INVALID_DISPATCH_CONTEXT: + reason = "FAST_FAIL_INVALID_DISPATCH_CONTEXT"; + break; + case MD_FAST_FAIL_INVALID_THREAD: + reason = "FAST_FAIL_INVALID_THREAD"; + break; + case MD_FAST_FAIL_INVALID_SYSCALL_NUMBER: + reason = "FAST_FAIL_INVALID_SYSCALL_NUMBER"; + break; + case MD_FAST_FAIL_INVALID_FILE_OPERATION: + reason = "FAST_FAIL_INVALID_FILE_OPERATION"; + break; + case MD_FAST_FAIL_LPAC_ACCESS_DENIED: + reason = "FAST_FAIL_LPAC_ACCESS_DENIED"; + break; + case MD_FAST_FAIL_GUARD_SS_FAILURE: + reason = "FAST_FAIL_GUARD_SS_FAILURE"; + break; + case MD_FAST_FAIL_LOADER_CONTINUITY_FAILURE: + reason = "FAST_FAIL_LOADER_CONTINUITY_FAILURE"; + break; + case MD_FAST_FAIL_GUARD_EXPORT_SUPPRESSION_FAILURE: + reason = "FAST_FAIL_GUARD_EXPORT_SUPPRESSION_FAILURE"; + break; + case MD_FAST_FAIL_INVALID_CONTROL_STACK: + reason = "FAST_FAIL_INVALID_CONTROL_STACK"; + break; + case MD_FAST_FAIL_SET_CONTEXT_DENIED: + reason = "FAST_FAIL_SET_CONTEXT_DENIED"; + break; + case MD_FAST_FAIL_INVALID_IAT: + reason = "FAST_FAIL_INVALID_IAT"; + break; + case MD_FAST_FAIL_HEAP_METADATA_CORRUPTION: + reason = "FAST_FAIL_HEAP_METADATA_CORRUPTION"; + break; + case MD_FAST_FAIL_PAYLOAD_RESTRICTION_VIOLATION: + reason = "FAST_FAIL_PAYLOAD_RESTRICTION_VIOLATION"; + break; + case MD_FAST_FAIL_LOW_LABEL_ACCESS_DENIED: + reason = "FAST_FAIL_LOW_LABEL_ACCESS_DENIED"; + break; + case MD_FAST_FAIL_ENCLAVE_CALL_FAILURE: + reason = "FAST_FAIL_ENCLAVE_CALL_FAILURE"; + break; + case MD_FAST_FAIL_UNHANDLED_LSS_EXCEPTON: + reason = "FAST_FAIL_UNHANDLED_LSS_EXCEPTON"; + break; + case MD_FAST_FAIL_ADMINLESS_ACCESS_DENIED: + reason = "FAST_FAIL_ADMINLESS_ACCESS_DENIED"; + break; + case MD_FAST_FAIL_UNEXPECTED_CALL: + reason = "FAST_FAIL_UNEXPECTED_CALL"; + break; + case MD_FAST_FAIL_CONTROL_INVALID_RETURN_ADDRESS: + reason = "FAST_FAIL_CONTROL_INVALID_RETURN_ADDRESS"; + break; + case MD_FAST_FAIL_UNEXPECTED_HOST_BEHAVIOR: + reason = "FAST_FAIL_UNEXPECTED_HOST_BEHAVIOR"; + break; + case MD_FAST_FAIL_FLAGS_CORRUPTION: + reason = "FAST_FAIL_FLAGS_CORRUPTION"; + break; + case MD_FAST_FAIL_VEH_CORRUPTION: + reason = "FAST_FAIL_VEH_CORRUPTION"; + break; + case MD_FAST_FAIL_ETW_CORRUPTION: + reason = "FAST_FAIL_ETW_CORRUPTION"; + break; + case MD_FAST_FAIL_RIO_ABORT: + reason = "FAST_FAIL_RIO_ABORT"; + break; + case MD_FAST_FAIL_INVALID_PFN: + reason = "FAST_FAIL_INVALID_PFN"; + break; + case MD_FAST_FAIL_GUARD_ICALL_CHECK_FAILURE_XFG: + reason = "FAST_FAIL_GUARD_ICALL_CHECK_FAILURE_XFG"; + break; + case MD_FAST_FAIL_CAST_GUARD: + reason = "FAST_FAIL_CAST_GUARD"; + break; + case MD_FAST_FAIL_HOST_VISIBILITY_CHANGE: + reason = "FAST_FAIL_HOST_VISIBILITY_CHANGE"; + break; + case MD_FAST_FAIL_KERNEL_CET_SHADOW_STACK_ASSIST: + reason = "FAST_FAIL_KERNEL_CET_SHADOW_STACK_ASSIST"; + break; + case MD_FAST_FAIL_PATCH_CALLBACK_FAILED: + reason = "FAST_FAIL_PATCH_CALLBACK_FAILED"; + break; + case MD_FAST_FAIL_NTDLL_PATCH_FAILED: + reason = "FAST_FAIL_NTDLL_PATCH_FAILED"; + break; + case MD_FAST_FAIL_INVALID_FLS_DATA: + reason = "FAST_FAIL_INVALID_FLS_DATA"; + break; + default: + reason = "EXCEPTION_STACK_BUFFER_OVERRUN"; + break; + } + } else { + reason = "EXCEPTION_STACK_BUFFER_OVERRUN"; + } break; case MD_EXCEPTION_CODE_WIN_HEAP_CORRUPTION: reason = "EXCEPTION_HEAP_CORRUPTION"; diff --git a/src/processor/minidump_processor_unittest.cc b/src/processor/minidump_processor_unittest.cc index 775a48ea..3af000d0 100644 --- a/src/processor/minidump_processor_unittest.cc +++ b/src/processor/minidump_processor_unittest.cc @@ -784,6 +784,22 @@ TEST_F(MinidumpProcessorTest, TestXStateAmd64ContextMinidump) { // breakpad. } +TEST_F(MinidumpProcessorTest, TestFastFailException) { + // This tests if we can understand fastfail exception subcodes. + // Dump is captured from a toy executable and is readable by windbg. + MinidumpProcessor processor(nullptr, nullptr /*&supplier, &resolver*/); + + string minidump_file = GetTestDataPath() + + "tiny-exe-fastfail.dmp"; + + ProcessState state; + ASSERT_EQ(processor.Process(minidump_file, &state), + google_breakpad::PROCESS_OK); + ASSERT_TRUE(state.crashed()); + ASSERT_EQ(state.threads()->size(), size_t(4)); + ASSERT_EQ(state.crash_reason(), "FAST_FAIL_FATAL_APP_EXIT"); +} + } // namespace int main(int argc, char* argv[]) { diff --git a/src/processor/testdata/tiny-exe-fastfail.dmp b/src/processor/testdata/tiny-exe-fastfail.dmp new file mode 100644 index 0000000000000000000000000000000000000000..f7a0a502ba9b0707fa835cca00699f117c6b85ab GIT binary patch literal 98722 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 QED0RW5;#xvgUsRo0oGHxT>t<8 literal 0 HcmV?d00001