Bug 932100 - Part 2: Move DLL blocklist code to mozglue. r=bsmedberg, r=glandium
authorDavid Major <dmajor@mozilla.com>
Tue, 12 Nov 2013 08:31:32 -0500
changeset 154563 33c8facd04680320804f1f377818250c3162d220
parent 154562 49671f1df4dad302d3aa5f624a52ce6790197fc6
child 154564 c0afa48bc2c33a00a3476a7fcf56607f88c75b14
push id25649
push userryanvm@gmail.com
push dateTue, 12 Nov 2013 20:24:15 +0000
treeherdermozilla-central@0b4b1330fafa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg, glandium
bugs932100
milestone28.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 932100 - Part 2: Move DLL blocklist code to mozglue. r=bsmedberg, r=glandium
b2g/app/nsBrowserApp.cpp
browser/app/nsBrowserApp.cpp
js/xpconnect/shell/xpcshell.cpp
mozglue/build/Makefile.in
mozglue/build/WindowsDllBlocklist.cpp
mozglue/build/WindowsDllBlocklist.h
mozglue/build/moz.build
toolkit/crashreporter/nsExceptionHandler.cpp
toolkit/crashreporter/nsExceptionHandler.h
toolkit/xre/moz.build
toolkit/xre/nsWindowsDllBlocklist.cpp
xpcom/build/nsXULAppAPI.h
xpcom/components/nsNativeComponentLoader.cpp
--- a/b2g/app/nsBrowserApp.cpp
+++ b/b2g/app/nsBrowserApp.cpp
@@ -37,16 +37,17 @@
 
 #include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL
 
 #ifdef MOZ_WIDGET_GONK
 # include <binder/ProcessState.h>
 #endif
 
 #include "mozilla/Telemetry.h"
+#include "mozilla/WindowsDllBlocklist.h"
 
 static void Output(const char *fmt, ... )
 {
   va_list ap;
   va_start(ap, fmt);
 
 #if defined(XP_WIN) && !MOZ_WINCONSOLE
   PRUnichar msg[2048];
@@ -87,29 +88,23 @@ class ScopedLogging
 public:
   ScopedLogging() { NS_LogInit(); }
   ~ScopedLogging() { NS_LogTerm(); }
 };
 
 XRE_GetFileFromPathType XRE_GetFileFromPath;
 XRE_CreateAppDataType XRE_CreateAppData;
 XRE_FreeAppDataType XRE_FreeAppData;
-#ifdef XRE_HAS_DLL_BLOCKLIST
-XRE_SetupDllBlocklistType XRE_SetupDllBlocklist;
-#endif
 XRE_TelemetryAccumulateType XRE_TelemetryAccumulate;
 XRE_mainType XRE_main;
 
 static const nsDynamicFunctionLoad kXULFuncs[] = {
     { "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
     { "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData },
     { "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData },
-#ifdef XRE_HAS_DLL_BLOCKLIST
-    { "XRE_SetupDllBlocklist", (NSFuncPtr*) &XRE_SetupDllBlocklist },
-#endif
     { "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate },
     { "XRE_main", (NSFuncPtr*) &XRE_main },
     { nullptr, nullptr }
 };
 
 static int do_main(int argc, char* argv[])
 {
   nsCOMPtr<nsIFile> appini;
@@ -205,16 +200,20 @@ int main(int argc, char* argv[])
 #if defined(XP_UNIX)
   struct rusage initialRUsage;
   gotCounters = !getrusage(RUSAGE_SELF, &initialRUsage);
 #elif defined(XP_WIN)
   IO_COUNTERS ioCounters;
   gotCounters = GetProcessIoCounters(GetCurrentProcess(), &ioCounters);
 #endif
 
+#ifdef HAS_DLL_BLOCKLIST
+  DllBlocklist_Initialize();
+#endif
+
   // We do this because of data in bug 771745
   XPCOMGlueEnablePreload();
 
   rv = XPCOMGlueStartup(exePath);
   if (NS_FAILED(rv)) {
     Output("Couldn't load XPCOM.\n");
     return 255;
   }
@@ -222,20 +221,16 @@ int main(int argc, char* argv[])
   *lastSlash = 0;
 
   rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
   if (NS_FAILED(rv)) {
     Output("Couldn't load XRE functions.\n");
     return 255;
   }
 
-#ifdef XRE_HAS_DLL_BLOCKLIST
-  XRE_SetupDllBlocklist();
-#endif
-
   if (gotCounters) {
 #if defined(XP_WIN)
     XRE_TelemetryAccumulate(mozilla::Telemetry::EARLY_GLUESTARTUP_READ_OPS,
                             int(ioCounters.ReadOperationCount));
     XRE_TelemetryAccumulate(mozilla::Telemetry::EARLY_GLUESTARTUP_READ_TRANSFER,
                             int(ioCounters.ReadTransferCount / 1024));
     IO_COUNTERS newIoCounters;
     if (GetProcessIoCounters(GetCurrentProcess(), &newIoCounters)) {
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -41,16 +41,17 @@
 #define snprintf _snprintf
 #define strcasecmp _stricmp
 #endif
 #include "BinaryPath.h"
 
 #include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL
 
 #include "mozilla/Telemetry.h"
+#include "mozilla/WindowsDllBlocklist.h"
 
 using namespace mozilla;
 
 #define kDesktopFolder "browser"
 #define kMetroFolder "metro"
 #define kMetroAppIniFilename "metroapp.ini"
 #ifdef XP_WIN
 #define kMetroTestFile "tests.ini"
@@ -149,31 +150,25 @@ static void AttachToTestHarness()
   FILE *fp = _fdopen(stdOut, "a");
   *stdout = *fp;
 }
 #endif
 
 XRE_GetFileFromPathType XRE_GetFileFromPath;
 XRE_CreateAppDataType XRE_CreateAppData;
 XRE_FreeAppDataType XRE_FreeAppData;
-#ifdef XRE_HAS_DLL_BLOCKLIST
-XRE_SetupDllBlocklistType XRE_SetupDllBlocklist;
-#endif
 XRE_TelemetryAccumulateType XRE_TelemetryAccumulate;
 XRE_StartupTimelineRecordType XRE_StartupTimelineRecord;
 XRE_mainType XRE_main;
 XRE_StopLateWriteChecksType XRE_StopLateWriteChecks;
 
 static const nsDynamicFunctionLoad kXULFuncs[] = {
     { "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
     { "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData },
     { "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData },
-#ifdef XRE_HAS_DLL_BLOCKLIST
-    { "XRE_SetupDllBlocklist", (NSFuncPtr*) &XRE_SetupDllBlocklist },
-#endif
     { "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate },
     { "XRE_StartupTimelineRecord", (NSFuncPtr*) &XRE_StartupTimelineRecord },
     { "XRE_main", (NSFuncPtr*) &XRE_main },
     { "XRE_StopLateWriteChecks", (NSFuncPtr*) &XRE_StopLateWriteChecks },
     { nullptr, nullptr }
 };
 
 static int do_main(int argc, char* argv[], nsIFile *xreDirectory)
@@ -602,27 +597,34 @@ int main(int argc, char* argv[])
   gotCounters = !getrusage(RUSAGE_SELF, &initialRUsage);
 #elif defined(XP_WIN)
   IO_COUNTERS ioCounters;
   gotCounters = GetProcessIoCounters(GetCurrentProcess(), &ioCounters);
 #endif
 
   nsIFile *xreDirectory;
 
+#ifdef HAS_DLL_BLOCKLIST
+  DllBlocklist_Initialize();
+
+  // In order to be effective against AppInit DLLs, the blocklist must be
+  // initialized before user32.dll is loaded into the process. If this assert
+  // ever fires, then the fix for bug 932100 has been defeated and the
+  // blocklist will miss AppInit DLLs. You should use a delayload or reorder
+  // the code to prevent user32.dll from loading during early startup.
+  MOZ_ASSERT(!GetModuleHandleA("user32.dll"));
+#endif
+
   nsresult rv = InitXPCOMGlue(argv[0], &xreDirectory);
   if (NS_FAILED(rv)) {
     return 255;
   }
 
   XRE_StartupTimelineRecord(mozilla::StartupTimeline::START, start);
 
-#ifdef XRE_HAS_DLL_BLOCKLIST
-  XRE_SetupDllBlocklist();
-#endif
-
   if (gotCounters) {
 #if defined(XP_WIN)
     XRE_TelemetryAccumulate(mozilla::Telemetry::EARLY_GLUESTARTUP_READ_OPS,
                             int(ioCounters.ReadOperationCount));
     XRE_TelemetryAccumulate(mozilla::Telemetry::EARLY_GLUESTARTUP_READ_TRANSFER,
                             int(ioCounters.ReadTransferCount / 1024));
     IO_COUNTERS newIoCounters;
     if (GetProcessIoCounters(GetCurrentProcess(), &newIoCounters)) {
--- a/js/xpconnect/shell/xpcshell.cpp
+++ b/js/xpconnect/shell/xpcshell.cpp
@@ -5,16 +5,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* XPConnect JavaScript interactive shell. */
 
 #include <stdio.h>
 
 #include "mozilla/Util.h"
+#include "mozilla/WindowsDllBlocklist.h"
 
 #include "nsXULAppAPI.h"
 #ifdef XP_MACOSX
 #include "xpcshellMacUtils.h"
 #endif
 #ifdef XP_WIN
 #include <windows.h>
 #include <shlobj.h>
@@ -33,18 +34,18 @@ main(int argc, char** argv, char** envp)
 #endif
 
 #ifdef HAVE_SETBUF
     // unbuffer stdout so that output is in the correct order; note that stderr
     // is unbuffered by default
     setbuf(stdout, 0);
 #endif
 
-#ifdef XRE_HAS_DLL_BLOCKLIST
-    XRE_SetupDllBlocklist();
+#ifdef HAS_DLL_BLOCKLIST
+    DllBlocklist_Initialize();
 #endif
 
     int result = XRE_XPCShellMain(argc, argv, envp);
 
 #ifdef XP_MACOSX
     FinishAutoreleasePool();
 #endif
 
--- a/mozglue/build/Makefile.in
+++ b/mozglue/build/Makefile.in
@@ -40,17 +40,24 @@ mozglue.def: mozglue.def.in
 
 GARBAGE += mozglue.def
 
 ifneq (,$(filter -DEFAULTLIB:mozcrt,$(MOZ_GLUE_LDFLAGS)))
 # Don't install the import library if we use mozcrt
 NO_INSTALL_IMPORT_LIBRARY = 1
 endif
 
-EXTRA_DSO_LDOPTS += $(MOZ_ZLIB_LIBS)
+
+EXTRA_DSO_LDOPTS += \
+	$(MOZ_ZLIB_LIBS) \
+	version.lib \
+	$(NULL)
+
+STL_FLAGS=
+
 endif
 
 ifeq (Darwin_1,$(OS_TARGET)_$(MOZ_REPLACE_MALLOC))
 EXTRA_DSO_LDOPTS += \
   -Wl,-U,_replace_init \
   -Wl,-U,_replace_malloc \
   -Wl,-U,_replace_posix_memalign \
   -Wl,-U,_replace_aligned_alloc \
rename from toolkit/xre/nsWindowsDllBlocklist.cpp
rename to mozglue/build/WindowsDllBlocklist.cpp
--- a/toolkit/xre/nsWindowsDllBlocklist.cpp
+++ b/mozglue/build/WindowsDllBlocklist.cpp
@@ -1,38 +1,31 @@
 /* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <windows.h>
 #include <winternl.h>
-
-#include <stdio.h>
-#include <string.h>
-
-#include <map>
+#include <io.h>
 
-#include "nsXULAppAPI.h"
+#pragma warning( push )
+#pragma warning( disable : 4275 4530 ) // See msvc-stl-wrapper.template.h
+#include <map>
+#pragma warning( pop )
 
+#define MOZ_NO_MOZALLOC
 #include "nsAutoPtr.h"
-#include "nsThreadUtils.h"
-
-#include "prlog.h"
 
 #include "nsWindowsDllInterceptor.h"
 #include "mozilla/WindowsVersion.h"
 #include "nsWindowsHelpers.h"
 
 using namespace mozilla;
 
-#ifdef MOZ_CRASHREPORTER
-#include "nsExceptionHandler.h"
-#endif
-
 #define ALL_VERSIONS   ((unsigned long long)-1LL)
 
 // DLLs sometimes ship without a version number, particularly early
 // releases. Blocking "version <= 0" has the effect of blocking unversioned
 // DLLs (since the call to get version info fails), but not blocking
 // any versioned instance.
 #define UNVERSIONED    ((unsigned long long)0LL)
 
@@ -148,34 +141,74 @@ static DllBlockInfo sWindowsDllBlocklist
 
 #ifndef STATUS_DLL_NOT_FOUND
 #define STATUS_DLL_NOT_FOUND ((DWORD)0xC0000135L)
 #endif
 
 // define this for very verbose dll load debug spew
 #undef DEBUG_very_verbose
 
-extern bool gInXPCOMLoadOnMainThread;
+static const char kBlockedDllsParameter[] = "BlockedDllList=";
+static const int kBlockedDllsParameterLen =
+  sizeof(kBlockedDllsParameter) - 1;
+
+static const char kBlocklistInitFailedParameter[] = "BlocklistInitFailed=";
+static const int kBlocklistInitFailedParameterLen =
+  sizeof(kBlocklistInitFailedParameter) - 1;
+
+static const char kUser32BeforeBlocklistParameter[] = "User32BeforeBlocklist=";
+static const int kUser32BeforeBlocklistParameterLen =
+  sizeof(kUser32BeforeBlocklistParameterLen) - 1;
+
+static DWORD sThreadLoadingXPCOMModule;
+static bool sBlocklistInitFailed;
+static bool sUser32BeforeBlocklist;
+
+// Duplicated from xpcom glue. Ideally this should be shared.
+static void
+printf_stderr(const char *fmt, ...)
+{
+  if (IsDebuggerPresent()) {
+    char buf[2048];
+    va_list args;
+    va_start(args, fmt);
+    vsnprintf(buf, sizeof(buf), fmt, args);
+    buf[sizeof(buf) - 1] = '\0';
+    va_end(args);
+    OutputDebugStringA(buf);
+  }
+
+  FILE *fp = _fdopen(_dup(2), "a");
+  if (!fp)
+      return;
+
+  va_list args;
+  va_start(args, fmt);
+  vfprintf(fp, fmt, args);
+  va_end(args);
+
+  fclose(fp);
+}
 
 namespace {
 
 typedef NTSTATUS (NTAPI *LdrLoadDll_func) (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileName, PHANDLE handle);
 
 static LdrLoadDll_func stub_LdrLoadDll = 0;
 
 template <class T>
 struct RVAMap {
   RVAMap(HANDLE map, DWORD offset) {
     SYSTEM_INFO info;
     GetSystemInfo(&info);
 
     DWORD alignedOffset = (offset / info.dwAllocationGranularity) *
                           info.dwAllocationGranularity;
 
-    NS_ASSERTION(offset - alignedOffset < info.dwAllocationGranularity, "Wtf");
+    MOZ_ASSERT(offset - alignedOffset < info.dwAllocationGranularity, "Wtf");
 
     mRealView = ::MapViewOfFile(map, FILE_MAP_READ, 0, alignedOffset,
                                 sizeof(T) + (offset - alignedOffset));
 
     mMappedView = mRealView ? reinterpret_cast<T*>((char*)mRealView + (offset - alignedOffset)) :
                               nullptr;
   }
   ~RVAMap() {
@@ -539,17 +572,17 @@ patched_LdrLoadDll (PWCHAR filePath, PUL
     }
   }
 
 continue_loading:
 #ifdef DEBUG_very_verbose
   printf_stderr("LdrLoadDll: continuing load... ('%S')\n", moduleFileName->Buffer);
 #endif
 
-  if (gInXPCOMLoadOnMainThread && NS_IsMainThread()) {
+  if (GetCurrentThreadId() == sThreadLoadingXPCOMModule) {
     // Check to ensure that the DLL has ASLR.
     full_fname = getFullPath(filePath, fname);
     if (!full_fname) {
       // uh, we couldn't find the DLL at all, so...
       printf_stderr("LdrLoadDll: Blocking load of '%s' (SearchPathW didn't find it?)\n", dllName);
       return STATUS_DLL_NOT_FOUND;
     }
 
@@ -561,36 +594,61 @@ continue_loading:
 
   return stub_LdrLoadDll(filePath, flags, moduleFileName, handle);
 }
 
 WindowsDllInterceptor NtDllIntercept;
 
 } // anonymous namespace
 
-void
-XRE_SetupDllBlocklist()
+NS_EXPORT void
+DllBlocklist_Initialize()
 {
+  if (GetModuleHandleA("user32.dll")) {
+    sUser32BeforeBlocklist = true;
+  }
+
   NtDllIntercept.Init("ntdll.dll");
 
   ReentrancySentinel::InitializeStatics();
 
   bool ok = NtDllIntercept.AddHook("LdrLoadDll", reinterpret_cast<intptr_t>(patched_LdrLoadDll), (void**) &stub_LdrLoadDll);
 
+  if (!ok) {
+    sBlocklistInitFailed = true;
 #ifdef DEBUG
-  if (!ok)
     printf_stderr ("LdrLoadDll hook failed, no dll blocklisting active\n");
 #endif
+  }
+}
 
-#ifdef MOZ_CRASHREPORTER
-  if (!ok) {
-    CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("DllBlockList Failed\n"));
+NS_EXPORT void
+DllBlocklist_SetInXPCOMLoadOnMainThread(bool inXPCOMLoadOnMainThread)
+{
+  if (inXPCOMLoadOnMainThread) {
+    MOZ_ASSERT(sThreadLoadingXPCOMModule == 0, "Only one thread should be doing this");
+    sThreadLoadingXPCOMModule = GetCurrentThreadId();
+  } else {
+    sThreadLoadingXPCOMModule = 0;
   }
-#endif
 }
 
-#ifdef MOZ_CRASHREPORTER
-void
-CrashReporter::WriteBlockedDlls(HANDLE file)
+NS_EXPORT void
+DllBlocklist_WriteNotes(HANDLE file)
 {
+  DWORD nBytes;
+
+  WriteFile(file, kBlockedDllsParameter, kBlockedDllsParameterLen, &nBytes, nullptr);
   DllBlockSet::Write(file);
+  WriteFile(file, "\n", 1, &nBytes, nullptr);
+
+  if (sBlocklistInitFailed) {
+    WriteFile(file, kBlocklistInitFailedParameter,
+              kBlocklistInitFailedParameterLen, &nBytes, nullptr);
+    WriteFile(file, "1\n", 2, &nBytes, nullptr);
+  }
+
+  if (sUser32BeforeBlocklist) {
+    WriteFile(file, kUser32BeforeBlocklistParameter,
+              kUser32BeforeBlocklistParameterLen, &nBytes, nullptr);
+    WriteFile(file, "1\n", 2, &nBytes, nullptr);
+  }
 }
-#endif
new file mode 100644
--- /dev/null
+++ b/mozglue/build/WindowsDllBlocklist.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_windowsdllblocklist_h
+#define mozilla_windowsdllblocklist_h
+
+#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
+
+#include <windows.h>
+#include "mozilla/GuardObjects.h"
+#include "nscore.h"
+
+#define HAS_DLL_BLOCKLIST
+
+NS_IMPORT void DllBlocklist_Initialize();
+NS_IMPORT void DllBlocklist_SetInXPCOMLoadOnMainThread(bool inXPCOMLoadOnMainThread);
+NS_IMPORT void DllBlocklist_WriteNotes(HANDLE file);
+
+class AutoSetXPCOMLoadOnMainThread
+{
+  public:
+    AutoSetXPCOMLoadOnMainThread(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) {
+      MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+      DllBlocklist_SetInXPCOMLoadOnMainThread(true);
+    }
+
+    ~AutoSetXPCOMLoadOnMainThread() {
+      DllBlocklist_SetInXPCOMLoadOnMainThread(false);
+    }
+
+  private:
+    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
+#endif // defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
+#endif // mozilla_windowsdllblocklist_h
--- a/mozglue/build/moz.build
+++ b/mozglue/build/moz.build
@@ -26,27 +26,33 @@ else:
         'dummy.cpp',
     ]
 
 if CONFIG['OS_TARGET'] == 'Android':
     SOURCES += [
         'BionicGlue.cpp',
     ]
 
+if CONFIG['OS_TARGET'] == 'WINNT':
+    SOURCES += [
+        'WindowsDllBlocklist.cpp',
+    ]
+
 if CONFIG['MOZ_NUWA_PROCESS']:
     EXPORTS.ipc += [
         'Nuwa.h',
     ]
     SOURCES += [
         'Nuwa.cpp',
     ]
 
 EXPORTS.mozilla += [
     'arm.h',
     'SSE.h',
+    'WindowsDllBlocklist.h',
 ]
 
 if CONFIG['CPU_ARCH'].startswith('x86'):
     SOURCES += [
         'SSE.cpp',
     ]
 
 if CONFIG['CPU_ARCH'] == 'arm':
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -78,16 +78,17 @@ using mozilla::InjectCrashRunnable;
 #include "nsCRT.h"
 #include "nsIFile.h"
 #include "prprf.h"
 #include <map>
 #include <vector>
 
 #include "mozilla/mozalloc_oom.h"
 #include "mozilla/LateWriteChecks.h"
+#include "mozilla/WindowsDllBlocklist.h"
 
 #if defined(XP_MACOSX)
 CFStringRef reporterClientAppID = CFSTR("org.mozilla.crashreporter");
 #endif
 #if defined(MOZ_WIDGET_ANDROID)
 #include "common/linux/file_id.h"
 #endif
 
@@ -217,21 +218,16 @@ static const int kAvailablePageFileParam
 static const char kAvailablePhysicalMemoryParameter[] = "AvailablePhysicalMemory=";
 static const int kAvailablePhysicalMemoryParameterLen =
   sizeof(kAvailablePhysicalMemoryParameter)-1;
 
 static const char kIsGarbageCollectingParameter[] = "IsGarbageCollecting=";
 static const int kIsGarbageCollectingParameterLen =
   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
 static Mutex* crashReporterAPILock;
 static Mutex* notesFieldLock;
 static AnnotationTable* crashReporterAPIData_Hash;
 static nsCString* crashReporterAPIData = nullptr;
 static nsCString* notesField = nullptr;
 static bool isGarbageCollecting;
 
@@ -540,19 +536,20 @@ bool MinidumpCallback(
         WriteFile(hFile, "\n", 1, &nBytes, nullptr);
       }
       if (isGarbageCollecting) {
         WriteFile(hFile, kIsGarbageCollectingParameter, kIsGarbageCollectingParameterLen,
                   &nBytes, nullptr);
         WriteFile(hFile, isGarbageCollecting ? "1" : "0", 1, &nBytes, nullptr);
         WriteFile(hFile, "\n", 1, &nBytes, nullptr);
       }
-      WriteFile(hFile, kBlockedDllsParameter, kBlockedDllsParameterLen, &nBytes, nullptr);
-      WriteBlockedDlls(hFile);
-      WriteFile(hFile, "\n", 1, &nBytes, nullptr);
+
+#ifdef HAS_DLL_BLOCKLIST
+      DllBlocklist_WriteNotes(hFile);
+#endif
 
       // Try to get some information about memory.
       MEMORYSTATUSEX statex;
       statex.dwLength = sizeof(statex);
       if (GlobalMemoryStatusEx(&statex)) {
         char buffer[128];
         int bufferLen;
 
--- a/toolkit/crashreporter/nsExceptionHandler.h
+++ b/toolkit/crashreporter/nsExceptionHandler.h
@@ -39,21 +39,16 @@ nsresult SetMinidumpPath(const nsAString
 // AnnotateCrashReport and AppendAppNotesToCrashReport may be called from any
 // thread in a chrome process, but may only be called from the main thread in
 // a content process.
 nsresult AnnotateCrashReport(const nsACString& key, const nsACString& data);
 nsresult AppendAppNotesToCrashReport(const nsACString& data);
 
 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 SetupExtraData(nsIFile* aAppDataDirectory,
                         const nsACString& aBuildID);
 bool GetLastRunCrashID(nsAString& id);
 
 // Registers an additional memory region to be included in the minidump
 nsresult RegisterAppMemory(void* ptr, size_t length);
 nsresult UnregisterAppMemory(void* ptr);
--- a/toolkit/xre/moz.build
+++ b/toolkit/xre/moz.build
@@ -19,17 +19,16 @@ MODULE = 'xulapp'
 
 if CONFIG['MOZ_INSTRUMENT_EVENT_LOOP']:
     EXPORTS += ['EventTracer.h']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     EXPORTS += ['nsWindowsDllInterceptor.h']
     SOURCES += [
         'nsNativeAppSupportWin.cpp',
-        'nsWindowsDllBlocklist.cpp',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     EXPORTS += ['MacQuirks.h']
     SOURCES += [
         'nsCommandLineServiceMac.cpp',
     ]
     SOURCES += [
         'MacApplicationDelegate.mm',
--- a/xpcom/build/nsXULAppAPI.h
+++ b/xpcom/build/nsXULAppAPI.h
@@ -432,22 +432,16 @@ XRE_API(bool,
                                    JSString* aCommand,
                                    void* aCallback))
 XRE_API(bool,
         XRE_ShutdownTestShell, ())
 
 XRE_API(void,
         XRE_InstallX11ErrorHandler, ())
 
-#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
-#define XRE_HAS_DLL_BLOCKLIST
-XRE_API(void,
-        XRE_SetupDllBlocklist, ())
-#endif
-
 XRE_API(void,
         XRE_TelemetryAccumulate, (int aID, uint32_t aSample))
 
 XRE_API(void,
         XRE_StartupTimelineRecord, (int aEvent, PRTime aWhen))
 
 XRE_API(void,
         XRE_InitOmnijar, (nsIFile* greOmni,
--- a/xpcom/components/nsNativeComponentLoader.cpp
+++ b/xpcom/components/nsNativeComponentLoader.cpp
@@ -27,16 +27,17 @@
 
 #include "nsComponentManager.h"
 #include "ManifestParser.h" // for LogMessage
 #include "nsCRTGlue.h"
 #include "nsThreadUtils.h"
 #include "nsTraceRefcntImpl.h"
 
 #include "nsIFile.h"
+#include "mozilla/WindowsDllBlocklist.h"
 
 #ifdef XP_WIN
 #include <windows.h>
 #endif
 
 #ifdef XP_MACOSX
 #include <signal.h>
 #endif
@@ -56,18 +57,16 @@ static PRLogModuleInfo *
 GetNativeModuleLoaderLog()
 {
     static PRLogModuleInfo *sLog;
     if (!sLog)
         sLog = PR_NewLogModule("nsNativeModuleLoader");
     return sLog;
 }
 
-bool gInXPCOMLoadOnMainThread = false;
-
 #define LOG(level, args) PR_LOG(GetNativeModuleLoaderLog(), level, args)
 
 NS_IMPL_QUERY_INTERFACE1(nsNativeModuleLoader,
                          mozilla::ModuleLoader)
 
 NS_IMPL_ADDREF_USING_AGGREGATOR(nsNativeModuleLoader,
                                 nsComponentManagerImpl::gComponentManager)
 NS_IMPL_RELEASE_USING_AGGREGATOR(nsNativeModuleLoader,
@@ -135,20 +134,22 @@ nsNativeModuleLoader::LoadModule(FileLoc
         NS_ASSERTION(data.module, "Corrupt mLibraries hash");
         LOG(PR_LOG_DEBUG,
             ("nsNativeModuleLoader::LoadModule(\"%s\") - found in cache",
              filePath.get()));
         return data.module;
     }
 
     // We haven't loaded this module before
-
-    gInXPCOMLoadOnMainThread = true;
-    rv = file->Load(&data.library);
-    gInXPCOMLoadOnMainThread = false;
+    {
+#ifdef HAS_DLL_BLOCKLIST
+      AutoSetXPCOMLoadOnMainThread guard;
+#endif
+      rv = file->Load(&data.library);
+    }
 
     if (NS_FAILED(rv)) {
         char errorMsg[1024] = "<unknown; can't get error from NSPR>";
 
         if (PR_GetErrorTextLength() < (int) sizeof(errorMsg))
             PR_GetErrorText(errorMsg);
 
         LogMessage("Failed to load native module at path '%s': (%lx) %s",