Bug 932100 - Part 2: Move DLL blocklist code to mozglue. r=bsmedberg, r=glandium, a=bajaj
authorDavid Major <dmajor@mozilla.com>
Fri, 22 Nov 2013 10:12:10 -0500
changeset 166574 5f97e043f2b80935d021b44a3f4bebc61d6cd0bb
parent 166573 5ddfaf5ea4f73ba857f126139daf310fa434f88c
child 166575 9cedd5ca03dc741526eec6ff00f86e1f2821bdc8
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg, glandium, bajaj
bugs932100
milestone27.0a2
Bug 932100 - Part 2: Move DLL blocklist code to mozglue. r=bsmedberg, r=glandium, a=bajaj
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_DisableWritePoisoningType XRE_DisableWritePoisoning;
 
 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_DisableWritePoisoning", (NSFuncPtr*) &XRE_DisableWritePoisoning },
     { 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
@@ -42,17 +42,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
@@ -24,24 +24,30 @@ 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',
     ]
 
 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/mozPoisonWrite.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",