Bug 733892; block reverting to the null last chance expception handler. r=ehsan

This commit is contained in:
Nicholas Cameron 2012-04-20 21:07:55 +12:00
parent 685c08c630
commit b056a47fa0
2 changed files with 47 additions and 4 deletions

View File

@ -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,

View File

@ -57,6 +57,8 @@
#include "client/windows/handler/exception_handler.h"
#include <DbgHelp.h>
#include <string.h>
#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<nsAutoPtr<DelayedNote> >* 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<intptr_t>(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