Bug 1285356: Fix blocklist initialization regressions; r=bsmedberg
authorAaron Klotz <aklotz@mozilla.com>
Thu, 07 Jul 2016 17:00:23 -0600
changeset 305927 4d06c9ff66cf7ef8c1a563ba4860bb12ac89c85e
parent 305926 923bcd0c37b0e9e2ad3de9b59c4818ad047b3004
child 305928 f4f17f746d1013fc179b8eefa7360e9838e93a60
push id30474
push usercbook@mozilla.com
push dateThu, 21 Jul 2016 14:25:10 +0000
treeherdermozilla-central@6b180266ac16 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg
bugs1285356
milestone50.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 1285356: Fix blocklist initialization regressions; r=bsmedberg MozReview-Commit-ID: AlWyzVhtPLL
browser/app/moz.build
browser/app/nsBrowserApp.cpp
ipc/app/MozillaRuntimeMain.cpp
ipc/app/moz.build
js/xpconnect/shell/moz.build
mozglue/build/WindowsDllBlocklist.cpp
toolkit/xre/nsEmbedFunctions.cpp
--- a/browser/app/moz.build
+++ b/browser/app/moz.build
@@ -51,16 +51,21 @@ if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_
         '/security/sandbox/chromium',
         '/security/sandbox/chromium-shim',
     ]
 
     USE_LIBS += [
         'sandbox_s',
     ]
 
+    DELAYLOAD_DLLS += [
+        'winmm.dll',
+        'user32.dll',
+    ]
+
 # Control the default heap size.
 # This is the heap returned by GetProcessHeap().
 # As we use the CRT heap, the default size is too large and wastes VM.
 #
 # The default heap size is 1MB on Win32.
 # The heap will grow if need be.
 #
 # Set it to 256k.  See bug 127069.
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -317,16 +317,30 @@ sizeof(XPCOM_DLL) - 1))
 #endif
   }
 
   return rv;
 }
 
 int main(int argc, char* argv[], char* envp[])
 {
+  mozilla::TimeStamp start = mozilla::TimeStamp::Now();
+
+#ifdef HAS_DLL_BLOCKLIST
+  DllBlocklist_Initialize();
+
+#ifdef DEBUG
+  // In order to be effective against AppInit DLLs, the blocklist must be
+  // initialized before user32.dll is loaded into the process (bug 932100).
+  if (GetModuleHandleA("user32.dll")) {
+    fprintf(stderr, "DLL blocklist was unable to intercept AppInit DLLs.\n");
+  }
+#endif
+#endif
+
 #ifdef MOZ_BROWSER_CAN_BE_CONTENTPROC
   // We are launching as a content process, delegate to the appropriate
   // main
   if (argc > 1 && IsArg(argv[1], "contentproc")) {
 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
     // We need to initialize the sandbox TargetServices before InitXPCOMGlue
     // because we might need the sandbox broker to give access to some files.
     if (IsSandboxedProcess() && !sandboxing::GetInitializedTargetServices()) {
@@ -344,32 +358,19 @@ int main(int argc, char* argv[], char* e
 
     // InitXPCOMGlue calls NS_LogInit, so we need to balance it here.
     NS_LogTerm();
 
     return result;
   }
 #endif
 
-  mozilla::TimeStamp start = mozilla::TimeStamp::Now();
 
   nsIFile *xreDirectory;
 
-#ifdef HAS_DLL_BLOCKLIST
-  DllBlocklist_Initialize();
-
-#ifdef DEBUG
-  // In order to be effective against AppInit DLLs, the blocklist must be
-  // initialized before user32.dll is loaded into the process (bug 932100).
-  if (GetModuleHandleA("user32.dll")) {
-    fprintf(stderr, "DLL blocklist was unable to intercept AppInit DLLs.\n");
-  }
-#endif
-#endif
-
   nsresult rv = InitXPCOMGlue(argv[0], &xreDirectory);
   if (NS_FAILED(rv)) {
     return 255;
   }
 
   XRE_StartupTimelineRecord(mozilla::StartupTimeline::START, start);
 
 #ifdef MOZ_BROWSER_CAN_BE_CONTENTPROC
--- a/ipc/app/MozillaRuntimeMain.cpp
+++ b/ipc/app/MozillaRuntimeMain.cpp
@@ -1,12 +1,19 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: sw=4 ts=4 et :
- * This Source Code Form is subject to the terms of the Mozilla Public
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 "../contentproc/plugin-container.cpp"
- 
+
+#include "mozilla/WindowsDllBlocklist.h"
+
 int
-main(int argc, char *argv[]) {
-    return content_process_main(argc, argv);
+main(int argc, char *argv[])
+{
+#ifdef HAS_DLL_BLOCKLIST
+  DllBlocklist_Initialize();
+#endif
+
+  return content_process_main(argc, argv);
 }
--- a/ipc/app/moz.build
+++ b/ipc/app/moz.build
@@ -32,25 +32,40 @@ LOCAL_INCLUDES += [
 if CONFIG['OS_TARGET'] != 'Android':
     SOURCES += [
         '../../dom/media/gmp/GMPLoader.cpp',
     ]
     USE_LIBS += [
         'rlz',
     ]
 
-if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
-    # For sandbox includes and the include dependencies those have
-    LOCAL_INCLUDES += [
-        '/security/sandbox/chromium',
-        '/security/sandbox/chromium-shim',
+# DELAYLOAD_DLLS in this block ensures that the DLL blocklist is functional
+if CONFIG['OS_ARCH'] == 'WINNT':
+    DELAYLOAD_DLLS += [
+        'nss3.dll',
     ]
 
-    USE_LIBS += [
-        'sandbox_s',
+    if CONFIG['MOZ_SANDBOX']:
+        # For sandbox includes and the include dependencies those have
+        LOCAL_INCLUDES += [
+            '/security/sandbox/chromium',
+            '/security/sandbox/chromium-shim',
+        ]
+
+        USE_LIBS += [
+            'sandbox_s',
+        ]
+
+        DELAYLOAD_DLLS += [
+            'winmm.dll',
+            'user32.dll',
+        ]
+
+    DELAYLOAD_DLLS += [
+        'xul.dll',
     ]
 
 if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_TARGET'] in ('Linux', 'Android'):
     USE_LIBS += [
         'mozsandbox',
     ]
 
     # gcc lto likes to put the top level asm in syscall.cc in a different partition
--- a/js/xpconnect/shell/moz.build
+++ b/js/xpconnect/shell/moz.build
@@ -26,25 +26,35 @@ LOCAL_INCLUDES += [
     '/toolkit/xre',
 ]
 
 if CONFIG['_MSC_VER']:
     # Always enter a Windows program through wmain, whether or not we're
     # a console application.
     WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup']
 
+# DELAYLOAD_DLLS in this block ensure that the DLL blocklist initializes
 if CONFIG['OS_ARCH'] == 'WINNT':
     RCINCLUDE = 'xpcshell.rc'
 
     if CONFIG['MOZ_SANDBOX']:
         # For sandbox includes and the include dependencies those have
         LOCAL_INCLUDES += [
             '/security/sandbox/chromium',
             '/security/sandbox/chromium-shim',
         ]
 
         USE_LIBS += [
             'sandbox_s',
         ]
 
+        DELAYLOAD_DLLS += [
+            'winmm.dll',
+            'user32.dll',
+        ]
+
+    DELAYLOAD_DLLS += [
+        'xul.dll',
+    ]
+
 CFLAGS += CONFIG['TK_CFLAGS']
 CXXFLAGS += CONFIG['TK_CFLAGS']
 OS_LIBS += CONFIG['TK_LIBS']
--- a/mozglue/build/WindowsDllBlocklist.cpp
+++ b/mozglue/build/WindowsDllBlocklist.cpp
@@ -238,16 +238,17 @@ static const char kBlocklistInitFailedPa
 static const int kBlocklistInitFailedParameterLen =
   sizeof(kBlocklistInitFailedParameter) - 1;
 
 static const char kUser32BeforeBlocklistParameter[] = "User32BeforeBlocklist=1\n";
 static const int kUser32BeforeBlocklistParameterLen =
   sizeof(kUser32BeforeBlocklistParameter) - 1;
 
 static DWORD sThreadLoadingXPCOMModule;
+static bool sBlocklistInitAttempted;
 static bool sBlocklistInitFailed;
 static bool sUser32BeforeBlocklist;
 
 // Duplicated from xpcom glue. Ideally this should be shared.
 void
 printf_stderr(const char *fmt, ...)
 {
   if (IsDebuggerPresent()) {
@@ -751,19 +752,26 @@ continue_loading:
 
 WindowsDllInterceptor NtDllIntercept;
 
 } // namespace
 
 MFBT_API void
 DllBlocklist_Initialize()
 {
+  if (sBlocklistInitAttempted) {
+    return;
+  }
+  sBlocklistInitAttempted = true;
+
   if (GetModuleHandleA("user32.dll")) {
     sUser32BeforeBlocklist = true;
   }
+  // Catch any missing DELAYLOADS for user32.dll
+  MOZ_ASSERT(!sUser32BeforeBlocklist);
 
   NtDllIntercept.Init("ntdll.dll");
 
   ReentrancySentinel::InitializeStatics();
 
   // We specifically use a detour, because there are cases where external
   // code also tries to hook LdrLoadDll, and doesn't know how to relocate our
   // nop space patches. (Bug 951827)
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -299,20 +299,16 @@ XRE_InitChildProcess(int aArgc,
                      char* aArgv[],
                      const XREChildData* aChildData)
 {
   NS_ENSURE_ARG_MIN(aArgc, 2);
   NS_ENSURE_ARG_POINTER(aArgv);
   NS_ENSURE_ARG_POINTER(aArgv[0]);
   MOZ_ASSERT(aChildData);
 
-#ifdef HAS_DLL_BLOCKLIST
-  DllBlocklist_Initialize();
-#endif
-
 #ifdef MOZ_JPROF
   // Call the code to install our handler
   setupProfilingStuff();
 #endif
 
 #if !defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_GONK)
   // On non-Fennec Gecko, the GMPLoader code resides in plugin-container,
   // and we must forward it through to the GMP code here.