From b056a47fa0ab9bd818a9994b961d45d140fa54c7 Mon Sep 17 00:00:00 2001 From: Nicholas Cameron Date: Fri, 20 Apr 2012 21:07:55 +1200 Subject: [PATCH] Bug 733892; block reverting to the null last chance expception handler. r=ehsan --- .../windows/handler/exception_handler.h | 8 ++-- toolkit/crashreporter/nsExceptionHandler.cpp | 43 +++++++++++++++++++ 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.h b/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.h index 70d8ae17681..aa1eaf6f8e9 100644 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.h +++ b/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.h @@ -238,6 +238,10 @@ class ExceptionHandler { void RegisterAppMemory(void *ptr, size_t length); void UnregisterAppMemory(void *ptr); + // Called on the exception thread when an unhandled exception occurs. + // Signals the exception handler thread to handle the exception. + static LONG WINAPI HandleException(EXCEPTION_POINTERS* exinfo); + private: friend class AutoExceptionHandler; @@ -268,10 +272,6 @@ class ExceptionHandler { // Runs the main loop for the exception handler thread. static DWORD WINAPI ExceptionHandlerThreadMain(void* lpParameter); - // Called on the exception thread when an unhandled exception occurs. - // Signals the exception handler thread to handle the exception. - static LONG WINAPI HandleException(EXCEPTION_POINTERS* exinfo); - #if _MSC_VER >= 1400 // MSVC 2005/8 // This function will be called by some CRT functions when they detect // that they were passed an invalid parameter. Note that in _DEBUG builds, diff --git a/toolkit/crashreporter/nsExceptionHandler.cpp b/toolkit/crashreporter/nsExceptionHandler.cpp index 770c4d3189d..09a8a2c1dd3 100644 --- a/toolkit/crashreporter/nsExceptionHandler.cpp +++ b/toolkit/crashreporter/nsExceptionHandler.cpp @@ -57,6 +57,8 @@ #include "client/windows/handler/exception_handler.h" #include #include + +#include "nsWindowsDllInterceptor.h" #elif defined(XP_MACOSX) #include "client/mac/crash_generation/client_info.h" #include "client/mac/crash_generation/crash_generation_server.h" @@ -264,6 +266,31 @@ static const char* kSubprocessBlacklist[] = { class DelayedNote; nsTArray >* gDelayedAnnotations; +#if defined(XP_WIN) +// the following are used to prevent other DLLs reverting the last chance +// exception handler to the windows default. Any attempt to change the +// unhandled exception filter or to reset it is ignored and our crash +// reporter is loaded instead (in case it became unloaded somehow) +typedef LPTOP_LEVEL_EXCEPTION_FILTER (WINAPI *SetUnhandledExceptionFilter_func) + (LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter); +static SetUnhandledExceptionFilter_func stub_SetUnhandledExceptionFilter = 0; +static WindowsDllInterceptor gKernel32Intercept; +static bool gBlockUnhandledExceptionFilter = true; + +static LPTOP_LEVEL_EXCEPTION_FILTER WINAPI +patched_SetUnhandledExceptionFilter (LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter) +{ + if (!gBlockUnhandledExceptionFilter || + lpTopLevelExceptionFilter == google_breakpad::ExceptionHandler::HandleException) { + // don't intercept + return stub_SetUnhandledExceptionFilter(lpTopLevelExceptionFilter); + } + + // intercept attempts to change the filter + return NULL; +} +#endif + #ifdef XP_MACOSX static cpu_type_t pref_cpu_types[2] = { #if defined(__i386__) @@ -822,6 +849,17 @@ nsresult SetExceptionHandler(nsILocalFile* aXREDirectory, #ifdef XP_WIN gExceptionHandler->set_handle_debug_exceptions(true); + + // protect the crash reporter from being unloaded + gKernel32Intercept.Init("kernel32.dll"); + bool ok = gKernel32Intercept.AddHook("SetUnhandledExceptionFilter", + reinterpret_cast(patched_SetUnhandledExceptionFilter), + (void**) &stub_SetUnhandledExceptionFilter); + +#ifdef DEBUG + if (!ok) + printf_stderr ("SetUnhandledExceptionFilter hook failed; crash reporter is vulnerable.\n"); +#endif #endif // store application start time @@ -1082,6 +1120,11 @@ static void OOPDeinit(); nsresult UnsetExceptionHandler() { +#ifdef XP_WIN + // allow SetUnhandledExceptionFilter + gBlockUnhandledExceptionFilter = false; +#endif + delete gExceptionHandler; // do this here in the unlikely case that we succeeded in allocating