mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-01 08:42:13 +00:00
Bug 927944 - Annotate crash reports with a list of DLLs that were blocked via the windows blocklist. Also fix the blocklist to recognize forward-slash as a path delimiter, r=ehsan
--HG-- extra : rebase_source : 5cbff13357fe96c5a86b5511a58b69176aa71817
This commit is contained in:
parent
0a63812eb6
commit
b5399b893f
@ -222,6 +222,11 @@ static const char kIsGarbageCollectingParameter[] = "IsGarbageCollecting=";
|
|||||||
static const int kIsGarbageCollectingParameterLen =
|
static const int kIsGarbageCollectingParameterLen =
|
||||||
sizeof(kIsGarbageCollectingParameter)-1;
|
sizeof(kIsGarbageCollectingParameter)-1;
|
||||||
|
|
||||||
|
#ifdef XP_WIN
|
||||||
|
static const char kBlockedDllsParameter[] = "BlockedDllList=";
|
||||||
|
static const int kBlockedDllsParameterLen = sizeof(kBlockedDllsParameter) - 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
// this holds additional data sent via the API
|
// this holds additional data sent via the API
|
||||||
static Mutex* crashReporterAPILock;
|
static Mutex* crashReporterAPILock;
|
||||||
static Mutex* notesFieldLock;
|
static Mutex* notesFieldLock;
|
||||||
@ -540,6 +545,9 @@ bool MinidumpCallback(
|
|||||||
WriteFile(hFile, isGarbageCollecting ? "1" : "0", 1, &nBytes, nullptr);
|
WriteFile(hFile, isGarbageCollecting ? "1" : "0", 1, &nBytes, nullptr);
|
||||||
WriteFile(hFile, "\n", 1, &nBytes, nullptr);
|
WriteFile(hFile, "\n", 1, &nBytes, nullptr);
|
||||||
}
|
}
|
||||||
|
WriteFile(hFile, kBlockedDllsParameter, kBlockedDllsParameterLen, &nBytes, nullptr);
|
||||||
|
WriteBlockedDlls(hFile);
|
||||||
|
WriteFile(hFile, "\n", 1, &nBytes, nullptr);
|
||||||
|
|
||||||
// Try to get some information about memory.
|
// Try to get some information about memory.
|
||||||
MEMORYSTATUSEX statex;
|
MEMORYSTATUSEX statex;
|
||||||
|
@ -44,6 +44,11 @@ nsresult AppendAppNotesToCrashReport(const nsACString& data);
|
|||||||
|
|
||||||
nsresult SetGarbageCollecting(bool collecting);
|
nsresult SetGarbageCollecting(bool collecting);
|
||||||
|
|
||||||
|
#ifdef XP_WIN
|
||||||
|
// Implemented by the blocklist, this method writes the blocklist annotation
|
||||||
|
void WriteBlockedDlls(HANDLE file);
|
||||||
|
#endif
|
||||||
|
|
||||||
nsresult SetRestartArgs(int argc, char** argv);
|
nsresult SetRestartArgs(int argc, char** argv);
|
||||||
nsresult SetupExtraData(nsIFile* aAppDataDirectory,
|
nsresult SetupExtraData(nsIFile* aAppDataDirectory,
|
||||||
const nsACString& aBuildID);
|
const nsACString& aBuildID);
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
|
||||||
#if defined(MOZ_CRASHREPORTER) && !defined(NO_BLOCKLIST_CRASHREPORTER)
|
#ifdef MOZ_CRASHREPORTER
|
||||||
#include "nsExceptionHandler.h"
|
#include "nsExceptionHandler.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -224,6 +224,10 @@ CheckASLR(const wchar_t* path)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This lock protects both the reentrancy sentinel and the crash reporter
|
||||||
|
// data structures.
|
||||||
|
static CRITICAL_SECTION sLock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Some versions of Windows call LoadLibraryEx to get the version information
|
* Some versions of Windows call LoadLibraryEx to get the version information
|
||||||
* for a DLL, which causes our patched LdrLoadDll implementation to re-enter
|
* for a DLL, which causes our patched LdrLoadDll implementation to re-enter
|
||||||
@ -270,16 +274,98 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static CRITICAL_SECTION sLock;
|
|
||||||
static std::map<DWORD, const char*>* sThreadMap;
|
static std::map<DWORD, const char*>* sThreadMap;
|
||||||
|
|
||||||
const char* mPreviousDllName;
|
const char* mPreviousDllName;
|
||||||
bool mReentered;
|
bool mReentered;
|
||||||
};
|
};
|
||||||
|
|
||||||
CRITICAL_SECTION ReentrancySentinel::sLock;
|
|
||||||
std::map<DWORD, const char*>* ReentrancySentinel::sThreadMap;
|
std::map<DWORD, const char*>* ReentrancySentinel::sThreadMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a linked list of DLLs that have been blocked. It doesn't use
|
||||||
|
* mozilla::LinkedList because this is an append-only list and doesn't need
|
||||||
|
* to be doubly linked.
|
||||||
|
*/
|
||||||
|
class DllBlockSet
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void Add(const char* name, unsigned long long version);
|
||||||
|
|
||||||
|
// Write the list of blocked DLLs to a file HANDLE. This method is run after
|
||||||
|
// a crash occurs and must therefore not use the heap, etc.
|
||||||
|
static void Write(HANDLE file);
|
||||||
|
|
||||||
|
private:
|
||||||
|
DllBlockSet(const char* name, unsigned long long version)
|
||||||
|
: mName(name)
|
||||||
|
, mVersion(version)
|
||||||
|
, mNext(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* mName; // points into the sWindowsDllBlocklist string
|
||||||
|
unsigned long long mVersion;
|
||||||
|
DllBlockSet* mNext;
|
||||||
|
|
||||||
|
static DllBlockSet* gFirst;
|
||||||
|
};
|
||||||
|
|
||||||
|
DllBlockSet* DllBlockSet::gFirst;
|
||||||
|
|
||||||
|
void
|
||||||
|
DllBlockSet::Add(const char* name, unsigned long long version)
|
||||||
|
{
|
||||||
|
EnterCriticalSection(&sLock);
|
||||||
|
for (DllBlockSet* b = gFirst; b; b = b->mNext) {
|
||||||
|
if (0 == strcmp(b->mName, name) && b->mVersion == version) {
|
||||||
|
LeaveCriticalSection(&sLock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Not already present
|
||||||
|
DllBlockSet* n = new DllBlockSet(name, version);
|
||||||
|
n->mNext = gFirst;
|
||||||
|
gFirst = n;
|
||||||
|
LeaveCriticalSection(&sLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DllBlockSet::Write(HANDLE file)
|
||||||
|
{
|
||||||
|
EnterCriticalSection(&sLock);
|
||||||
|
DWORD nBytes;
|
||||||
|
|
||||||
|
// Because this method is called after a crash occurs, and uses heap memory,
|
||||||
|
// protect this entire block with a structured exception handler.
|
||||||
|
__try {
|
||||||
|
for (DllBlockSet* b = gFirst; b; b = b->mNext) {
|
||||||
|
// write name[,v.v.v.v];
|
||||||
|
WriteFile(file, b->mName, strlen(b->mName), &nBytes, nullptr);
|
||||||
|
if (b->mVersion != -1) {
|
||||||
|
WriteFile(file, ",", 1, &nBytes, nullptr);
|
||||||
|
uint16_t parts[4];
|
||||||
|
parts[0] = b->mVersion >> 48;
|
||||||
|
parts[1] = (b->mVersion >> 32) & 0xFFFF;
|
||||||
|
parts[2] = (b->mVersion >> 16) & 0xFFFF;
|
||||||
|
parts[3] = b->mVersion & 0xFFFF;
|
||||||
|
for (int p = 0; p < 4; ++p) {
|
||||||
|
char buf[32];
|
||||||
|
ltoa(parts[p], buf, 10);
|
||||||
|
WriteFile(file, buf, strlen(buf), &nBytes, nullptr);
|
||||||
|
if (p != 3) {
|
||||||
|
WriteFile(file, ".", 1, &nBytes, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WriteFile(file, ";", 1, &nBytes, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
__except (EXCEPTION_EXECUTE_HANDLER) { }
|
||||||
|
|
||||||
|
LeaveCriticalSection(&sLock);
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
wchar_t* getFullPath (PWCHAR filePath, wchar_t* fname)
|
wchar_t* getFullPath (PWCHAR filePath, wchar_t* fname)
|
||||||
{
|
{
|
||||||
@ -308,6 +394,17 @@ wchar_t* getFullPath (PWCHAR filePath, wchar_t* fname)
|
|||||||
return full_fname;
|
return full_fname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No builtin function to find the last character matching a set
|
||||||
|
static wchar_t* lastslash(wchar_t* s, int len)
|
||||||
|
{
|
||||||
|
for (wchar_t* c = s + len - 1; c >= s; --c) {
|
||||||
|
if (*c == L'\\' || *c == L'/') {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS NTAPI
|
static NTSTATUS NTAPI
|
||||||
patched_LdrLoadDll (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileName, PHANDLE handle)
|
patched_LdrLoadDll (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileName, PHANDLE handle)
|
||||||
{
|
{
|
||||||
@ -334,7 +431,7 @@ patched_LdrLoadDll (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileNam
|
|||||||
goto continue_loading;
|
goto continue_loading;
|
||||||
}
|
}
|
||||||
|
|
||||||
dll_part = wcsrchr(fname, L'\\');
|
dll_part = lastslash(fname, len);
|
||||||
if (dll_part) {
|
if (dll_part) {
|
||||||
dll_part = dll_part + 1;
|
dll_part = dll_part + 1;
|
||||||
len -= dll_part - fname;
|
len -= dll_part - fname;
|
||||||
@ -400,6 +497,8 @@ patched_LdrLoadDll (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileNam
|
|||||||
goto continue_loading;
|
goto continue_loading;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned long long fVersion = ALL_VERSIONS;
|
||||||
|
|
||||||
if (info->maxVersion != ALL_VERSIONS) {
|
if (info->maxVersion != ALL_VERSIONS) {
|
||||||
ReentrancySentinel sentinel(dllName);
|
ReentrancySentinel sentinel(dllName);
|
||||||
if (sentinel.BailOut()) {
|
if (sentinel.BailOut()) {
|
||||||
@ -426,7 +525,7 @@ patched_LdrLoadDll (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileNam
|
|||||||
if (GetFileVersionInfoW(full_fname, 0, infoSize, infoData) &&
|
if (GetFileVersionInfoW(full_fname, 0, infoSize, infoData) &&
|
||||||
VerQueryValueW(infoData, L"\\", (LPVOID*) &vInfo, &vInfoLen))
|
VerQueryValueW(infoData, L"\\", (LPVOID*) &vInfo, &vInfoLen))
|
||||||
{
|
{
|
||||||
unsigned long long fVersion =
|
fVersion =
|
||||||
((unsigned long long)vInfo->dwFileVersionMS) << 32 |
|
((unsigned long long)vInfo->dwFileVersionMS) << 32 |
|
||||||
((unsigned long long)vInfo->dwFileVersionLS);
|
((unsigned long long)vInfo->dwFileVersionLS);
|
||||||
|
|
||||||
@ -440,6 +539,7 @@ patched_LdrLoadDll (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileNam
|
|||||||
|
|
||||||
if (!load_ok) {
|
if (!load_ok) {
|
||||||
printf_stderr("LdrLoadDll: Blocking load of '%s' -- see http://www.mozilla.com/en-US/blocklist/\n", dllName);
|
printf_stderr("LdrLoadDll: Blocking load of '%s' -- see http://www.mozilla.com/en-US/blocklist/\n", dllName);
|
||||||
|
DllBlockSet::Add(info->name, fVersion);
|
||||||
return STATUS_DLL_NOT_FOUND;
|
return STATUS_DLL_NOT_FOUND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -485,9 +585,17 @@ XRE_SetupDllBlocklist()
|
|||||||
printf_stderr ("LdrLoadDll hook failed, no dll blocklisting active\n");
|
printf_stderr ("LdrLoadDll hook failed, no dll blocklisting active\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MOZ_CRASHREPORTER) && !defined(NO_BLOCKLIST_CRASHREPORTER)
|
#ifdef MOZ_CRASHREPORTER
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("DllBlockList Failed\n"));
|
CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("DllBlockList Failed\n"));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MOZ_CRASHREPORTER
|
||||||
|
void
|
||||||
|
CrashReporter::WriteBlockedDlls(HANDLE file)
|
||||||
|
{
|
||||||
|
DllBlockSet::Write(file);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user