Bug 1035125 Part 9: Link Chromium sandbox into firefox.exe instead of having a separate DLL. r?aklotz, r?glandium draft
authorBob Owen <bobowencode@gmail.com>
Sun, 15 May 2016 16:41:40 +0100
changeset 367186 e8f550c440a17fe6e6d6844e3914b0ae922cc5d5
parent 367185 7bf9f9ec88671786b5d299f5f7f40408d61750fc
child 520934 635b79e213f7c98fcfa7c430729ad9b80d2b3d5b
push id18160
push userbobowencode@gmail.com
push dateSun, 15 May 2016 15:43:05 +0000
reviewersaklotz, glandium
bugs1035125
milestone49.0a1
Bug 1035125 Part 9: Link Chromium sandbox into firefox.exe instead of having a separate DLL. r?aklotz, r?glandium MozReview-Commit-ID: 1vgDPjpcwz3
browser/app/moz.build
browser/app/nsBrowserApp.cpp
browser/installer/package-manifest.in
browser/installer/windows/nsis/shared.nsh
js/xpconnect/shell/moz.build
js/xpconnect/shell/xpcshell.cpp
js/xpconnect/src/XPCShellImpl.cpp
security/sandbox/chromium-shim/sandbox/win/sandboxLogging.cpp
security/sandbox/chromium-shim/sandbox/win/sandboxLogging.h
security/sandbox/win/SandboxInitialization.cpp
security/sandbox/win/SandboxInitialization.h
security/sandbox/win/src/sandboxbroker/moz.build
security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
security/sandbox/win/src/sandboxbroker/sandboxBroker.h
toolkit/library/moz.build
toolkit/xre/nsAppRunner.cpp
xpcom/build/XREShellData.h
xpcom/build/moz.build
xpcom/build/nsXREAppData.h
xpcom/build/nsXULAppAPI.h
xpcom/glue/AppData.cpp
--- a/browser/app/moz.build
+++ b/browser/app/moz.build
@@ -40,16 +40,27 @@ if CONFIG['_MSC_VER']:
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     RCINCLUDE = 'splash.rc'
     DEFINES['MOZ_PHOENIX'] = True
 
 for cdm in CONFIG['MOZ_EME_MODULES']:
     DEFINES['MOZ_%s_EME' % cdm.upper()] = True
 
+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',
+    ]
+
+    USE_LIBS += [
+        'sandbox_s',
+    ]
+
 # 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
@@ -37,16 +37,19 @@
 #define XRE_DONT_SUPPORT_XPSP2
 #endif
 #define XRE_WANT_ENVIRON
 #include "nsWindowsWMain.cpp"
 #if defined(_MSC_VER) && (_MSC_VER < 1900)
 #define snprintf _snprintf
 #endif
 #define strcasecmp _stricmp
+#ifdef MOZ_SANDBOX
+#include "mozilla/sandboxing/SandboxInitialization.h"
+#endif
 #endif
 #include "BinaryPath.h"
 
 #include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL
 
 #include "mozilla/Telemetry.h"
 #include "mozilla/WindowsDllBlocklist.h"
 
@@ -174,17 +177,24 @@ static int do_main(int argc, char* argv[
     }
     argv[2] = argv[0];
     argv += 2;
     argc -= 2;
   } else if (argc > 1 && IsArg(argv[1], "xpcshell")) {
     for (int i = 1; i < argc; i++) {
       argv[i] = argv[i + 1];
     }
-    return XRE_XPCShellMain(--argc, argv, envp);
+
+    XREShellData shellData;
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+    shellData.sandboxBrokerServices =
+      sandboxing::GetInitializedBrokerServices();
+#endif
+
+    return XRE_XPCShellMain(--argc, argv, envp, &shellData);
   }
 
   if (appini) {
     nsXREAppData *appData;
     rv = XRE_CreateAppData(appini, &appData);
     if (NS_FAILED(rv)) {
       Output("Couldn't read application.ini");
       return 255;
@@ -212,16 +222,28 @@ static int do_main(int argc, char* argv[
   nsCOMPtr<nsIFile> appSubdir;
   greDir->Clone(getter_AddRefs(appSubdir));
   appSubdir->Append(NS_LITERAL_STRING(kDesktopFolder));
 
   SetStrongPtr(appData.directory, static_cast<nsIFile*>(appSubdir.get()));
   // xreDirectory already has a refcount from NS_NewLocalFile
   appData.xreDirectory = xreDirectory;
 
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+  sandbox::BrokerServices* brokerServices =
+    sandboxing::GetInitializedBrokerServices();
+#if defined(MOZ_CONTENT_SANDBOX)
+  if (!brokerServices) {
+    Output("Couldn't initialize the broker services.\n");
+    return 255;
+  }
+#endif
+  appData.sandboxBrokerServices = brokerServices;
+#endif
+
   return XRE_main(argc, argv, &appData, mainFlags);
 }
 
 static bool
 FileExists(const char *path)
 {
 #ifdef XP_WIN
   wchar_t wideDir[MAX_PATH];
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -761,17 +761,16 @@
 @RESPATH@/chrome/pippki@JAREXT@
 @RESPATH@/chrome/pippki.manifest
 @RESPATH@/components/pipnss.xpt
 @RESPATH@/components/pippki.xpt
 
 ; For process sandboxing
 #if defined(MOZ_SANDBOX)
 #if defined(XP_WIN)
-@BINPATH@/@DLL_PREFIX@sandboxbroker@DLL_SUFFIX@
 #if defined(WOW_HELPER)
 @BINPATH@/wow_helper.exe
 #endif
 #endif
 #endif
 
 ; for Solaris SPARC
 #ifdef SOLARIS
--- a/browser/installer/windows/nsis/shared.nsh
+++ b/browser/installer/windows/nsis/shared.nsh
@@ -1363,17 +1363,16 @@
   ; returns after the first check.
   Push "end"
   Push "AccessibleMarshal.dll"
   Push "freebl3.dll"
   Push "nssckbi.dll"
   Push "nspr4.dll"
   Push "nssdbm3.dll"
   Push "mozsqlite3.dll"
-  Push "sandboxbroker.dll"
   Push "xpcom.dll"
   Push "crashreporter.exe"
   Push "updater.exe"
   Push "${FileMainEXE}"
 !macroend
 !define PushFilesToCheck "!insertmacro PushFilesToCheck"
 
 
--- a/js/xpconnect/shell/moz.build
+++ b/js/xpconnect/shell/moz.build
@@ -29,14 +29,25 @@ LOCAL_INCLUDES += [
 if CONFIG['_MSC_VER']:
     # Always enter a Windows program through wmain, whether or not we're
     # a console application.
     WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup']
 
 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',
+        ]
+
 CFLAGS += CONFIG['TK_CFLAGS']
 CXXFLAGS += CONFIG['TK_CFLAGS']
 OS_LIBS += CONFIG['TK_LIBS']
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wshadow']
--- a/js/xpconnect/shell/xpcshell.cpp
+++ b/js/xpconnect/shell/xpcshell.cpp
@@ -17,16 +17,19 @@
 #ifdef XP_WIN
 #include <windows.h>
 #include <shlobj.h>
 
 // we want a wmain entry point
 #define XRE_DONT_PROTECT_DLL_LOAD
 #define XRE_WANT_ENVIRON
 #include "nsWindowsWMain.cpp"
+#ifdef MOZ_SANDBOX
+#include "mozilla/sandboxing/SandboxInitialization.h"
+#endif
 #endif
 
 #ifdef MOZ_WIDGET_GTK
 #include <gtk/gtk.h>
 #endif
 
 int
 main(int argc, char** argv, char** envp)
@@ -45,16 +48,22 @@ main(int argc, char** argv, char** envp)
     // unbuffer stdout so that output is in the correct order; note that stderr
     // is unbuffered by default
     setbuf(stdout, 0);
 
 #ifdef HAS_DLL_BLOCKLIST
     DllBlocklist_Initialize();
 #endif
 
-    int result = XRE_XPCShellMain(argc, argv, envp);
+    XREShellData shellData;
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+    shellData.sandboxBrokerServices =
+      mozilla::sandboxing::GetInitializedBrokerServices();
+#endif
+
+    int result = XRE_XPCShellMain(argc, argv, envp, &shellData);
 
 #ifdef XP_MACOSX
     FinishAutoreleasePool();
 #endif
 
     return result;
 }
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -1260,18 +1260,21 @@ GetCurrentWorkingDirectory(nsAString& wo
     workingDirectory = NS_ConvertUTF8toUTF16(cwd);
 #endif
     return true;
 }
 
 static JSSecurityCallbacks shellSecurityCallbacks;
 
 int
-XRE_XPCShellMain(int argc, char** argv, char** envp)
+XRE_XPCShellMain(int argc, char** argv, char** envp,
+                 const XREShellData* aShellData)
 {
+    MOZ_ASSERT(aShellData);
+
     JSRuntime* rt;
     JSContext* cx;
     int result = 0;
     nsresult rv;
 
     gErrFile = stderr;
     gOutFile = stdout;
     gInFile = stdin;
@@ -1523,17 +1526,19 @@ XRE_XPCShellMain(int argc, char** argv, 
         BrowserTabsRemoteAutostart();
 #ifdef XP_WIN
         // Plugin may require audio session if installed plugin can initialize
         // asynchronized.
         AutoAudioSession audioSession;
 
 #if defined(MOZ_SANDBOX)
         // Required for sandboxed child processes.
-        if (!SandboxBroker::Initialize()) {
+        if (aShellData->sandboxBrokerServices) {
+          SandboxBroker::Initialize(aShellData->sandboxBrokerServices);
+        } else {
           NS_WARNING("Failed to initialize broker services, sandboxed "
                      "processes will fail to start.");
         }
 #endif
 #endif
 
         {
             JS::Rooted<JSObject*> glob(cx, holder->GetJSObject());
--- a/security/sandbox/chromium-shim/sandbox/win/sandboxLogging.cpp
+++ b/security/sandbox/chromium-shim/sandbox/win/sandboxLogging.cpp
@@ -7,36 +7,16 @@
 #include "sandboxLogging.h"
 
 #include "base/strings/utf_string_conversions.h"
 #include "sandbox/win/src/sandbox_policy.h"
 
 namespace mozilla {
 namespace sandboxing {
 
-void
-ApplyLoggingPolicy(sandbox::TargetPolicy& aPolicy)
-{
-  // Add dummy rules, so that we can log in the interception code.
-  // We already have a file interception set up for the client side of pipes.
-  // Also, passing just "dummy" for file system policy causes win_utils.cc
-  // IsReparsePoint() to loop.
-  aPolicy.AddRule(sandbox::TargetPolicy::SUBSYS_NAMED_PIPES,
-                  sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY, L"dummy");
-  aPolicy.AddRule(sandbox::TargetPolicy::SUBSYS_PROCESS,
-                  sandbox::TargetPolicy::PROCESS_MIN_EXEC, L"dummy");
-  aPolicy.AddRule(sandbox::TargetPolicy::SUBSYS_REGISTRY,
-                  sandbox::TargetPolicy::REG_ALLOW_READONLY,
-                  L"HKEY_CURRENT_USER\\dummy");
-  aPolicy.AddRule(sandbox::TargetPolicy::SUBSYS_SYNC,
-                  sandbox::TargetPolicy::EVENTS_ALLOW_READONLY, L"dummy");
-  aPolicy.AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES,
-                  sandbox::TargetPolicy::HANDLES_DUP_BROKER, L"dummy");
-}
-
 static LogFunction sLogFunction = nullptr;
 
 void
 ProvideLogFunction(LogFunction aLogFunction)
 {
   sLogFunction = aLogFunction;
 }
 
--- a/security/sandbox/chromium-shim/sandbox/win/sandboxLogging.h
+++ b/security/sandbox/chromium-shim/sandbox/win/sandboxLogging.h
@@ -19,19 +19,16 @@ class TargetPolicy;
 
 namespace mozilla {
 namespace sandboxing {
 
 // This is used to pass a LogCallback to the sandboxing code, as the logging
 // requires code to which we cannot link directly.
 void ProvideLogFunction(LogFunction aLogFunction);
 
-// Set up dummy interceptions via the broker, so we can log calls.
-void ApplyLoggingPolicy(sandbox::TargetPolicy& aPolicy);
-
 // Log a "BLOCKED" msg to the browser console and, if DEBUG build, stderr.
 // If the logging of a stack trace is enabled then the default aFramesToSkip
 // will start from our caller's caller, which should normally be the function
 // that triggered the interception.
 void LogBlocked(const char* aFunctionName, const char* aContext = nullptr,
                 uint32_t aFramesToSkip = 2);
 
 // Convenience functions to convert to char*.
--- a/security/sandbox/win/SandboxInitialization.cpp
+++ b/security/sandbox/win/SandboxInitialization.cpp
@@ -37,10 +37,45 @@ GetInitializedTargetServices()
 }
 
 void
 LowerSandbox()
 {
   GetInitializedTargetServices()->LowerToken();
 }
 
+static sandbox::BrokerServices*
+InitializeBrokerServices()
+{
+  sandbox::BrokerServices* brokerServices =
+    sandbox::SandboxFactory::GetBrokerServices();
+  if (!brokerServices) {
+    return nullptr;
+  }
+
+  if (brokerServices->Init() != sandbox::SBOX_ALL_OK) {
+    return nullptr;
+  }
+
+  // Comment below copied from Chromium code.
+  // Precreate the desktop and window station used by the renderers.
+  // IMPORTANT: This piece of code needs to run as early as possible in the
+  // process because it will initialize the sandbox broker, which requires
+  // the process to swap its window station. During this time all the UI
+  // will be broken. This has to run before threads and windows are created.
+  sandbox::TargetPolicy* policy = brokerServices->CreatePolicy();
+  sandbox::ResultCode result = policy->CreateAlternateDesktop(true);
+  policy->Release();
+
+  return brokerServices;
+}
+
+sandbox::BrokerServices*
+GetInitializedBrokerServices()
+{
+  static sandbox::BrokerServices* sInitializedBrokerServices =
+    InitializeBrokerServices();
+
+  return sInitializedBrokerServices;
+}
+
 } // sandboxing
 } // mozilla
--- a/security/sandbox/win/SandboxInitialization.h
+++ b/security/sandbox/win/SandboxInitialization.h
@@ -3,16 +3,17 @@
 /* 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_sandboxing_SandboxInitialization_h
 #define mozilla_sandboxing_SandboxInitialization_h
 
 namespace sandbox {
+class BrokerServices;
 class TargetServices;
 }
 
 namespace mozilla {
 // Note the Chromium code just uses a bare sandbox namespace, which makes using
 // sandbox for our namespace painful.
 namespace sandboxing {
 
@@ -24,12 +25,19 @@ namespace sandboxing {
 sandbox::TargetServices* GetInitializedTargetServices();
 
 /**
  * Lowers the permissions on the process sandbox.
  * Provided because the GMP sandbox needs to be lowered from the executable.
  */
 void LowerSandbox();
 
+/**
+ * Initializes (if required) and returns the Chromium sandbox BrokerServices.
+ *
+ * @return the BrokerServices or null if the creation or initialization failed.
+ */
+sandbox::BrokerServices* GetInitializedBrokerServices();
+
 } // sandboxing
 } // mozilla
 
 #endif // mozilla_sandboxing_SandboxInitialization_h
--- a/security/sandbox/win/src/sandboxbroker/moz.build
+++ b/security/sandbox/win/src/sandboxbroker/moz.build
@@ -1,38 +1,33 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-SharedLibrary('sandboxbroker')
-
-USE_LIBS += [
-    'nspr',
-    'sandbox_s',
-]
-
 SOURCES += [
     'sandboxBroker.cpp',
 ]
 
 EXPORTS += [
     'sandboxBroker.h',
 ]
 
-for var in ('UNICODE', '_UNICODE', 'NS_NO_XPCOM', 'SANDBOX_EXPORTS'):
+for var in ('UNICODE', '_UNICODE', 'SANDBOX_EXPORTS'):
     DEFINES[var] = True
 
 LOCAL_INCLUDES += [
     '/security/sandbox/chromium',
 ]
 
 DISABLE_STL_WRAPPING = True
 
 OS_LIBS += [
     'dbghelp',
 ]
 
 if CONFIG['_MSC_VER']:
     CXXFLAGS += [
         '-wd4275', # non dll-interface class exception used as base for dll-interface class
     ]
+
+FINAL_LIBRARY = 'xul'
--- a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
+++ b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
@@ -2,41 +2,30 @@
 /* vim: set ts=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 "sandboxBroker.h"
 
 #include "base/win/windows_version.h"
+#include "mozilla/Assertions.h"
 #include "sandbox/win/src/sandbox.h"
-#include "sandbox/win/src/sandbox_factory.h"
 #include "sandbox/win/src/security_level.h"
-#include "mozilla/sandboxing/sandboxLogging.h"
 
 namespace mozilla
 {
 
 sandbox::BrokerServices *SandboxBroker::sBrokerService = nullptr;
 
 /* static */
-bool
-SandboxBroker::Initialize()
+void
+SandboxBroker::Initialize(sandbox::BrokerServices* aBrokerServices)
 {
-  sBrokerService = sandbox::SandboxFactory::GetBrokerServices();
-  if (!sBrokerService) {
-    return false;
-  }
-
-  if (sBrokerService->Init() != sandbox::SBOX_ALL_OK) {
-    sBrokerService = nullptr;
-    return false;
-  }
-
-  return true;
+  sBrokerService = aBrokerServices;
 }
 
 SandboxBroker::SandboxBroker()
 {
   if (sBrokerService) {
     mPolicy = sBrokerService->CreatePolicy();
   } else {
     mPolicy = nullptr;
@@ -54,17 +43,17 @@ SandboxBroker::LaunchApp(const wchar_t *
   }
 
   // Set stdout and stderr, to allow inheritance for logging.
   mPolicy->SetStdoutHandle(::GetStdHandle(STD_OUTPUT_HANDLE));
   mPolicy->SetStderrHandle(::GetStdHandle(STD_ERROR_HANDLE));
 
   // If logging enabled, set up the policy.
   if (aEnableLogging) {
-    mozilla::sandboxing::ApplyLoggingPolicy(*mPolicy);
+    ApplyLoggingPolicy();
   }
 
 #if defined(DEBUG)
   // Allow write access to TEMP directory in debug builds for logging purposes.
   // The path from GetTempPathW can have a length up to MAX_PATH + 1, including
   // the null, so we need MAX_PATH + 2, so we can add an * to the end.
   wchar_t tempPath[MAX_PATH + 2];
   uint32_t pathLen = ::GetTempPathW(MAX_PATH + 1, tempPath);
@@ -480,16 +469,38 @@ SandboxBroker::AddTargetPeer(HANDLE aPee
   if (!sBrokerService) {
     return false;
   }
 
   sandbox::ResultCode result = sBrokerService->AddTargetPeer(aPeerProcess);
   return (sandbox::SBOX_ALL_OK == result);
 }
 
+void
+SandboxBroker::ApplyLoggingPolicy()
+{
+  MOZ_ASSERT(mPolicy);
+
+  // Add dummy rules, so that we can log in the interception code.
+  // We already have a file interception set up for the client side of pipes.
+  // Also, passing just "dummy" for file system policy causes win_utils.cc
+  // IsReparsePoint() to loop.
+  mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_NAMED_PIPES,
+                  sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY, L"dummy");
+  mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_PROCESS,
+                  sandbox::TargetPolicy::PROCESS_MIN_EXEC, L"dummy");
+  mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_REGISTRY,
+                  sandbox::TargetPolicy::REG_ALLOW_READONLY,
+                  L"HKEY_CURRENT_USER\\dummy");
+  mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_SYNC,
+                  sandbox::TargetPolicy::EVENTS_ALLOW_READONLY, L"dummy");
+  mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES,
+                  sandbox::TargetPolicy::HANDLES_DUP_BROKER, L"dummy");
+}
+
 SandboxBroker::~SandboxBroker()
 {
   if (mPolicy) {
     mPolicy->Release();
     mPolicy = nullptr;
   }
 }
 
--- a/security/sandbox/win/src/sandboxbroker/sandboxBroker.h
+++ b/security/sandbox/win/src/sandboxbroker/sandboxBroker.h
@@ -2,38 +2,32 @@
 /* vim: set ts=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/. */
 
 #ifndef __SECURITY_SANDBOX_SANDBOXBROKER_H__
 #define __SECURITY_SANDBOX_SANDBOXBROKER_H__
 
-#ifdef SANDBOX_EXPORTS
-#define SANDBOX_EXPORT __declspec(dllexport)
-#else
-#define SANDBOX_EXPORT __declspec(dllimport)
-#endif
-
 #include <stdint.h>
 #include <windows.h>
 
 namespace sandbox {
   class BrokerServices;
   class TargetPolicy;
 }
 
 namespace mozilla {
 
-class SANDBOX_EXPORT SandboxBroker
+class SandboxBroker
 {
 public:
   SandboxBroker();
 
-  static bool Initialize();
+  static void Initialize(sandbox::BrokerServices* aBrokerServices);
 
   bool LaunchApp(const wchar_t *aPath,
                  const wchar_t *aArguments,
                  const bool aEnableLogging,
                  void **aProcessHandle);
   virtual ~SandboxBroker();
 
   // Security levels for different types of processes
@@ -51,16 +45,20 @@ public:
   // File system permissions
   bool AllowReadFile(wchar_t const *file);
   bool AllowReadWriteFile(wchar_t const *file);
   bool AllowDirectory(wchar_t const *dir);
 
   // Exposes AddTargetPeer from broker services, so that none sandboxed
   // processes can be added as handle duplication targets.
   bool AddTargetPeer(HANDLE aPeerProcess);
+
+  // Set up dummy interceptions via the broker, so we can log calls.
+  void ApplyLoggingPolicy();
+
 private:
   static sandbox::BrokerServices *sBrokerService;
   sandbox::TargetPolicy *mPolicy;
 };
 
 } // mozilla
 
 #endif
--- a/toolkit/library/moz.build
+++ b/toolkit/library/moz.build
@@ -97,21 +97,16 @@ if CONFIG['OS_ARCH'] == 'WINNT' and not 
 DIRS += ['gtest']
 
 # js needs to come after xul for now, because it is an archive and its content
 # is discarded when it comes first.
 USE_LIBS += [
     'js',
 ]
 
-if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
-    USE_LIBS += [
-        'sandboxbroker',
-    ]
-
 USE_LIBS += [
     'gkmedias',
     'lgpllibs',
     'nspr',
     'nss',
     'sqlite',
     'zlib',
 ]
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -3368,20 +3368,21 @@ XREMain::XRE_mainInit(bool* aExitFlag)
 
         SaveWordToEnv("MOZ_CRASHREPORTER_STRINGS_OVERRIDE", overridePath);
       }
     }
   }
 #endif
 
 #if defined(MOZ_SANDBOX) && defined(XP_WIN)
-  bool brokerInitialized = SandboxBroker::Initialize();
-  Telemetry::Accumulate(Telemetry::SANDBOX_BROKER_INITIALIZED,
-                        brokerInitialized);
-  if (!brokerInitialized) {
+  if (mAppData->sandboxBrokerServices) {
+    SandboxBroker::Initialize(mAppData->sandboxBrokerServices);
+    Telemetry::Accumulate(Telemetry::SANDBOX_BROKER_INITIALIZED, true);
+  } else {
+    Telemetry::Accumulate(Telemetry::SANDBOX_BROKER_INITIALIZED, false);
 #if defined(MOZ_CONTENT_SANDBOX)
     // If we're sandboxing content and we fail to initialize, then crashing here
     // seems like the sensible option.
     if (BrowserTabsRemoteAutostart()) {
       MOZ_CRASH("Failed to initialize broker services, can't continue.");
     }
 #endif
     // Otherwise just warn for the moment, as most things will work.
new file mode 100644
--- /dev/null
+++ b/xpcom/build/XREShellData.h
@@ -0,0 +1,29 @@
+/* -*- 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/. */
+
+#ifndef XREShellData_h
+#define XREShellData_h
+
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+namespace sandbox {
+class BrokerServices;
+}
+#endif
+
+/**
+ * Data needed by XRE_XPCShellMain.
+ */
+struct XREShellData
+{
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+  /**
+   * Chromium sandbox BrokerServices.
+   */
+  sandbox::BrokerServices* sandboxBrokerServices;
+#endif
+};
+
+#endif // XREShellData_h
--- a/xpcom/build/moz.build
+++ b/xpcom/build/moz.build
@@ -7,16 +7,17 @@
 EXPORTS += [
     'nsXPCOM.h',
     'nsXPCOMCID.h',
     'nsXPCOMCIDInternal.h',
     'nsXREAppData.h',
     'nsXULAppAPI.h',
     'XREChildData.h',
     'xrecore.h',
+    'XREShellData.h',
 ]
 
 EXPORTS.mozilla += [
     'FileLocation.h',
     'IOInterposer.h',
     'LateWriteChecks.h',
     'Omnijar.h',
     'PoisonIOInterposer.h',
--- a/xpcom/build/nsXREAppData.h
+++ b/xpcom/build/nsXREAppData.h
@@ -7,16 +7,22 @@
 #ifndef nsXREAppData_h
 #define nsXREAppData_h
 
 #include <stdint.h>
 #include "mozilla/Attributes.h"
 
 class nsIFile;
 
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+namespace sandbox {
+class BrokerServices;
+}
+#endif
+
 /**
  * Application-specific data needed to start the apprunner.
  *
  * @note When this structure is allocated and manipulated by XRE_CreateAppData,
  *       string fields will be allocated with moz_xmalloc, and interface pointers
  *       are strong references.
  */
 struct nsXREAppData
@@ -123,16 +129,23 @@ struct nsXREAppData
    *   UAppData = $HOME/$profile
    */
   const char* profile;
 
   /**
    * The application name to use in the User Agent string.
    */
   const char* UAName;
+
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+  /**
+   * Chromium sandbox BrokerServices.
+   */
+  sandbox::BrokerServices* sandboxBrokerServices;
+#endif
 };
 
 /**
  * Indicates whether or not the profile migrator service may be
  * invoked at startup when creating a profile.
  */
 #define NS_XRE_ENABLE_PROFILE_MIGRATOR (1 << 1)
 
--- a/xpcom/build/nsXULAppAPI.h
+++ b/xpcom/build/nsXULAppAPI.h
@@ -15,16 +15,17 @@
 #include "nsXREAppData.h"
 #include "js/TypeDecls.h"
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Vector.h"
 #include "mozilla/TimeStamp.h"
 #include "XREChildData.h"
+#include "XREShellData.h"
 
 /**
  * A directory service key which provides the platform-correct "application
  * data" directory as follows, where $name and $vendor are as defined above and
  * $vendor is optional:
  *
  * Windows:
  *   HOME = Documents and Settings\$USER\Application Data
@@ -482,16 +483,17 @@ XRE_API(void,
         XRE_ProcLoaderClientInit, (pid_t, int,
                                    mozilla::Vector<int>& aReservedFds));
 XRE_API(void,
         XRE_ProcLoaderPreload, (const char* aProgramDir,
                                 const nsXREAppData* aAppData));
 #endif // MOZ_B2G_LOADER
 
 XRE_API(int,
-        XRE_XPCShellMain, (int argc, char** argv, char** envp))
+        XRE_XPCShellMain, (int argc, char** argv, char** envp,
+                           const XREShellData* aShellData))
 
 #if MOZ_WIDGET_GTK == 2
 XRE_API(void,
         XRE_GlibInit, ())
 #endif
 
 #endif // _nsXULAppAPI_h__
--- a/xpcom/glue/AppData.cpp
+++ b/xpcom/glue/AppData.cpp
@@ -60,16 +60,20 @@ ScopedAppData::ScopedAppData(const nsXRE
 
   if (aAppData->size > offsetof(nsXREAppData, crashReporterURL)) {
     SetAllocatedString(this->crashReporterURL, aAppData->crashReporterURL);
   }
 
   if (aAppData->size > offsetof(nsXREAppData, UAName)) {
     SetAllocatedString(this->UAName, aAppData->UAName);
   }
+
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+  sandboxBrokerServices = aAppData->sandboxBrokerServices;
+#endif
 }
 
 ScopedAppData::~ScopedAppData()
 {
   SetAllocatedString(this->vendor, nullptr);
   SetAllocatedString(this->name, nullptr);
   SetAllocatedString(this->remotingName, nullptr);
   SetAllocatedString(this->version, nullptr);