Bug 1284897 - Add mechanism to libsandbox_s to track names of files that have been given special sandbox access permissions (PermissionsService). r=bobowen, r=glandium
☠☠ backed out by 4c7e6ba1ab9b ☠ ☠
authorDavid Parks <dparks@mozilla.com>
Tue, 14 Feb 2017 15:08:40 -0800
changeset 344174 71b9ac06a60a570b6a7ce4560a685f642122a9d4
parent 344173 4e81ec8850dcaf402ce8b23f146859cfea377f41
child 344175 0740284125d33ce825023ae66fdf07484f62f0c4
push id31402
push usercbook@mozilla.com
push dateWed, 22 Feb 2017 13:33:50 +0000
treeherdermozilla-central@f5372cb6c3c7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbobowen, glandium
bugs1284897
milestone54.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 1284897 - Add mechanism to libsandbox_s to track names of files that have been given special sandbox access permissions (PermissionsService). r=bobowen, r=glandium Hook this into the browser via the XREAppData. This patch does not include the changes to Chromium source code.
browser/app/nsBrowserApp.cpp
security/sandbox/chromium-shim/sandbox/win/permissionsService.cpp
security/sandbox/chromium-shim/sandbox/win/permissionsService.h
security/sandbox/moz.build
security/sandbox/win/SandboxInitialization.cpp
security/sandbox/win/SandboxInitialization.h
security/sandbox/win/src/sandboxpermissions/moz.build
security/sandbox/win/src/sandboxpermissions/sandboxPermissions.cpp
security/sandbox/win/src/sandboxpermissions/sandboxPermissions.h
toolkit/xre/Bootstrap.h
toolkit/xre/nsAppRunner.cpp
xpcom/build/XREAppData.h
xpcom/glue/XREAppData.cpp
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -212,23 +212,26 @@ static int do_main(int argc, char* argv[
     // no -app flag so we use the compiled-in app data
     config.appData = &sAppData;
     config.appDataPath = kDesktopFolder;
   }
 
 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
   sandbox::BrokerServices* brokerServices =
     sandboxing::GetInitializedBrokerServices();
+  sandboxing::PermissionsService* permissionsService =
+    sandboxing::GetPermissionsService();
 #if defined(MOZ_CONTENT_SANDBOX)
   if (!brokerServices) {
     Output("Couldn't initialize the broker services.\n");
     return 255;
   }
 #endif
   config.sandboxBrokerServices = brokerServices;
+  config.sandboxPermissionsService = permissionsService;
 #endif
 
 #ifdef LIBFUZZER
   if (getenv("LIBFUZZER"))
     gBootstrap->XRE_LibFuzzerSetDriver(fuzzer::FuzzerDriver);
 #endif
 
   return gBootstrap->XRE_main(argc, argv, config);
new file mode 100644
--- /dev/null
+++ b/security/sandbox/chromium-shim/sandbox/win/permissionsService.cpp
@@ -0,0 +1,136 @@
+/* -*- 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/. */
+
+/* SandboxPermissions.cpp - Special permissions granted to sandboxed processes */
+
+#include "permissionsService.h"
+#include <algorithm>
+#include <winternl.h>
+
+namespace mozilla {
+namespace sandboxing {
+
+static const std::wstring ZONE_IDENTIFIER_STR(L":ZONE.IDENTIFIER");
+static const std::wstring ZONE_ID_DATA_STR(L":ZONE.IDENTIFIER:$DATA");
+
+bool
+StringEndsWith(const std::wstring& str, const std::wstring& strEnding)
+{
+  if (strEnding.size() > str.size()) {
+    return false;
+  }
+  return std::equal(strEnding.rbegin(), strEnding.rend(), str.rbegin());
+}
+
+// Converts NT device internal filenames to normal user-space by stripping
+// the prefixes and suffixes from the file name.
+std::wstring
+GetPlainFileName(const wchar_t* aNTFileName)
+{
+  while (*aNTFileName == L'\\' || *aNTFileName == L'.' ||
+         *aNTFileName == L'?' || *aNTFileName == L':' ) {
+    ++aNTFileName;
+  }
+  std::wstring nameCopy(aNTFileName);
+  std::transform(nameCopy.begin(), nameCopy.end(), nameCopy.begin(), towupper);
+  if (StringEndsWith(nameCopy, ZONE_ID_DATA_STR)) {
+    nameCopy = nameCopy.substr(0, nameCopy.size() - ZONE_ID_DATA_STR.size());
+  } else if (StringEndsWith(nameCopy, ZONE_IDENTIFIER_STR)) {
+    nameCopy = nameCopy.substr(0, nameCopy.size() - ZONE_IDENTIFIER_STR.size());
+  }
+  return nameCopy;
+}
+
+/* static */ PermissionsService*
+PermissionsService::GetInstance()
+{
+  static PermissionsService sPermissionsService;
+  return &sPermissionsService;
+}
+
+PermissionsService::PermissionsService() :
+  mFileAccessViolationFunc(nullptr)
+{
+}
+
+void
+PermissionsService::GrantFileAccess(uint32_t aProcessId,
+                                    const wchar_t* aFilename,
+                                    bool aPermitWrite)
+{
+  FilePermissionMap& permissions = mProcessFilePermissions[aProcessId];
+  std::wstring filename = GetPlainFileName(aFilename);
+  permissions[filename] |= aPermitWrite;
+}
+
+void
+PermissionsService::SetFileAccessViolationFunc(FileAccessViolationFunc aFavFunc)
+{
+  mFileAccessViolationFunc = aFavFunc;
+}
+
+void
+PermissionsService::ReportBlockedFile(bool aNeedsWrite)
+{
+  if (mFileAccessViolationFunc) {
+    mFileAccessViolationFunc(aNeedsWrite);
+  }
+}
+
+bool
+PermissionsService::UserGrantedFileAccess(uint32_t aProcessId,
+                                          const wchar_t* aFilename,
+                                          uint32_t aAccess,
+                                          uint32_t aDisposition)
+{
+  // There are 3 types of permissions:
+  // * Those available w/ read-only permission
+  // * Those available w/ read-only AND read-write permission
+  // * Those always forbidden.
+  const uint32_t FORBIDDEN_FLAGS =
+    FILE_EXECUTE | FILE_LIST_DIRECTORY | FILE_TRAVERSE | STANDARD_RIGHTS_EXECUTE;
+  const uint32_t NEEDS_WRITE_FLAGS =
+    FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA |
+    DELETE | STANDARD_RIGHTS_WRITE;
+  bool needsWrite =
+    (aAccess & NEEDS_WRITE_FLAGS) || (aDisposition != FILE_OPEN);
+
+  if (aAccess & FORBIDDEN_FLAGS) {
+    ReportBlockedFile(needsWrite);
+    return false;
+  }
+
+  auto permissions = mProcessFilePermissions.find(aProcessId);
+  if (permissions == mProcessFilePermissions.end()) {
+    ReportBlockedFile(needsWrite);
+    return false;  // process has no special file access at all
+  }
+
+  std::wstring filename = GetPlainFileName(aFilename);
+  auto itPermission = permissions->second.find(filename);
+  if (itPermission == permissions->second.end()) {
+    ReportBlockedFile(needsWrite);
+    return false;  // process has no access to this file
+  }
+
+  // We have read permission.  Check for write permission if requested.
+  if (!needsWrite || itPermission->second) {
+    return true;
+  }
+
+  // We needed write access but didn't have it.
+  ReportBlockedFile(needsWrite);
+  return false;
+}
+
+void
+PermissionsService::RemovePermissionsForProcess(uint32_t aProcessId)
+{
+  mProcessFilePermissions.erase(aProcessId);
+}
+
+}   // namespace sandboxing
+}   // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/security/sandbox/chromium-shim/sandbox/win/permissionsService.h
@@ -0,0 +1,78 @@
+/* -*- 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 mozilla_sandboxing_permissionsService_h
+#define mozilla_sandboxing_permissionsService_h
+
+#include <unordered_map>
+
+namespace mozilla {
+namespace sandboxing {
+
+/*
+ * Represents additional permissions granted to sandboxed processes.
+ * The members are virtual so that the object can be created in any
+ * library that links with libsandbox_s and then shared with and used
+ * by libXUL, which does not link with libsandbox_s.
+ */
+class PermissionsService
+{
+public:
+  static PermissionsService* GetInstance();
+
+  /*
+   * Allow future access to aFilename by the plugin process.
+   */
+  virtual void GrantFileAccess(uint32_t aProcessId, const wchar_t* aFilename,
+                               bool aPermitWrite);
+
+  /*
+   * Type of callback function that the sandbox uses to report file
+   * accesses that were denied.
+   * Parameter is a boolean indicating the access request was read-only
+   * (false) or read-write (true)
+   */
+  typedef void (*FileAccessViolationFunc)(bool);
+
+  /*
+   * Sets the callback function that is called whenever a file access is
+   * denied by the sandbox.
+   */
+  virtual void SetFileAccessViolationFunc(FileAccessViolationFunc aFavFunc);
+
+  /*
+   * Returns true if the user has granted the sandboxed plugin process the
+   * requested permission to open the file.
+   * Calls aFavFunc with file info if the file access was blocked.
+   */
+  virtual bool UserGrantedFileAccess(uint32_t aProcessId, const wchar_t* aFilename,
+                                     uint32_t aAccess, uint32_t aDisposition);
+
+  /*
+   * Clears all special file access for the given plugin process.
+   */
+  virtual void RemovePermissionsForProcess(uint32_t aProcessId);
+
+private:
+  PermissionsService();
+  void ReportBlockedFile(bool aNeedsWrite);
+
+  // Maps from filenames to a boolean indicating read-only permission (false) or
+  // read-write permission (true).
+  typedef std::unordered_map<std::wstring, bool> FilePermissionMap;
+
+  // Maps from process ID to map of user-granted file permissions for
+  // that process.
+  typedef std::unordered_map<uint32_t, FilePermissionMap> ProcessFilePermissionMap;
+
+  ProcessFilePermissionMap mProcessFilePermissions;
+  FileAccessViolationFunc mFileAccessViolationFunc;
+};
+
+} // namespace sandboxing
+} // namespace mozilla
+
+#endif // mozilla_sandboxing_permissionsService_h
--- a/security/sandbox/moz.build
+++ b/security/sandbox/moz.build
@@ -14,33 +14,36 @@ if CONFIG['OS_ARCH'] == 'Linux':
 elif CONFIG['OS_ARCH'] == 'Darwin':
     DIRS += ['mac']
 elif CONFIG['OS_ARCH'] == 'WINNT':
     Library('sandbox_s')
     FORCE_STATIC_LIB = True
 
     DIRS += [
         'win/src/sandboxbroker',
+        'win/src/sandboxpermissions',
         'win/src/sandboxtarget',
     ]
 
     if (CONFIG['CPU_ARCH'] == 'x86' and CONFIG['_MSC_VER'] and not
             CONFIG['CLANG_CL']):
         DIRS += ['win/wow_helper']
 
     EXPORTS.mozilla.sandboxing += [
         'chromium-shim/sandbox/win/loggingCallbacks.h',
         'chromium-shim/sandbox/win/loggingTypes.h',
+        'chromium-shim/sandbox/win/permissionsService.h',
         'chromium-shim/sandbox/win/sandboxLogging.h',
         'win/SandboxInitialization.h',
     ]
 
     SOURCES += [
         'chromium-shim/base/files/file_path.cpp',
         'chromium-shim/base/logging.cpp',
+        'chromium-shim/sandbox/win/permissionsService.cpp',
         'chromium-shim/sandbox/win/sandboxLogging.cpp',
         'chromium/base/at_exit.cc',
         'chromium/base/base_switches.cc',
         'chromium/base/callback_internal.cc',
         'chromium/base/cpu.cc',
         'chromium/base/debug/alias.cc',
         'chromium/base/debug/profiler.cc',
         'chromium/base/hash.cc',
--- a/security/sandbox/win/SandboxInitialization.cpp
+++ b/security/sandbox/win/SandboxInitialization.cpp
@@ -2,16 +2,17 @@
 /* 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 "SandboxInitialization.h"
 
 #include "sandbox/win/src/sandbox_factory.h"
+#include "mozilla/sandboxing/permissionsService.h"
 
 namespace mozilla {
 namespace sandboxing {
 
 static sandbox::TargetServices*
 InitializeTargetServices()
 {
   sandbox::TargetServices* targetServices =
@@ -72,10 +73,15 @@ sandbox::BrokerServices*
 GetInitializedBrokerServices()
 {
   static sandbox::BrokerServices* sInitializedBrokerServices =
     InitializeBrokerServices();
 
   return sInitializedBrokerServices;
 }
 
+PermissionsService* GetPermissionsService()
+{
+  return PermissionsService::GetInstance();
+}
+
 } // sandboxing
 } // mozilla
--- a/security/sandbox/win/SandboxInitialization.h
+++ b/security/sandbox/win/SandboxInitialization.h
@@ -16,16 +16,18 @@ class TargetServices;
 // function defined in one of the Chromium sandbox cc files.
 extern "C" bool IsSandboxedProcess();
 
 namespace mozilla {
 // Note the Chromium code just uses a bare sandbox namespace, which makes using
 // sandbox for our namespace painful.
 namespace sandboxing {
 
+class PermissionsService;
+
 /**
  * Initializes (if required) and returns the Chromium sandbox TargetServices.
  *
  * @return the TargetServices or null if the creation or initialization failed.
  */
 sandbox::TargetServices* GetInitializedTargetServices();
 
 /**
@@ -36,12 +38,14 @@ 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();
 
+PermissionsService* GetPermissionsService();
+
 } // sandboxing
 } // mozilla
 
 #endif // mozilla_sandboxing_SandboxInitialization_h
new file mode 100644
--- /dev/null
+++ b/security/sandbox/win/src/sandboxpermissions/moz.build
@@ -0,0 +1,22 @@
+# -*- Mode: python; 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/.
+
+SOURCES += [
+    'sandboxPermissions.cpp',
+]
+
+EXPORTS += [
+    'sandboxPermissions.h',
+]
+
+for var in ('UNICODE', '_UNICODE'):
+    DEFINES[var] = True
+
+LOCAL_INCLUDES += [
+    '/security/sandbox/win',
+]
+
+FINAL_LIBRARY = 'xul'
new file mode 100644
--- /dev/null
+++ b/security/sandbox/win/src/sandboxpermissions/sandboxPermissions.cpp
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "sandboxPermissions.h"
+#include "mozilla/Assertions.h"
+#include "mozilla/sandboxing/permissionsService.h"
+
+namespace mozilla
+{
+
+sandboxing::PermissionsService* SandboxPermissions::sPermissionsService = nullptr;
+
+void
+SandboxPermissions::Initialize(sandboxing::PermissionsService* aPermissionsService,
+                               FileAccessViolationFunc aFileAccessViolationFunc)
+{
+  sPermissionsService = aPermissionsService;
+  sPermissionsService->SetFileAccessViolationFunc(aFileAccessViolationFunc);
+}
+
+void
+SandboxPermissions::GrantFileAccess(uint32_t aProcessId, const wchar_t* aFilename,
+                                    bool aPermitWrite)
+{
+  MOZ_ASSERT(sPermissionsService, "Must initialize sandbox PermissionsService");
+  sPermissionsService->GrantFileAccess(aProcessId, aFilename, aPermitWrite);
+}
+
+void
+SandboxPermissions::RemovePermissionsForProcess(uint32_t aProcessId)
+{
+  if (!sPermissionsService) {
+    return;   // No permissions service was initialized
+  }
+  sPermissionsService->RemovePermissionsForProcess(aProcessId);
+}
+
+}  // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/security/sandbox/win/src/sandboxpermissions/sandboxPermissions.h
@@ -0,0 +1,57 @@
+/* -*- 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 mozilla_sandboxing_sandboxPermissions_h
+#define mozilla_sandboxing_sandboxPermissions_h
+
+#include <stdint.h>
+#include <windows.h>
+
+namespace mozilla {
+
+namespace sandboxing {
+  class PermissionsService;
+}
+
+/*
+ * This object wraps a PermissionsService object.  This object is available
+ * in libXUL but PermissionsService is not.
+ */
+class SandboxPermissions
+{
+public:
+  /*
+   * Type of callback function that the sandbox uses to report file
+   * accesses that were denied.
+   * Parameter is a boolean indicating the access request was read-only
+   * (false) or read-write (true)
+   */
+  typedef void (*FileAccessViolationFunc)(bool);
+
+  /*
+   * Prepare this object by providing it with the internal permissions service.
+   */
+  static void Initialize(sandboxing::PermissionsService* aPermissionsService,
+                         FileAccessViolationFunc aFileAccessViolationFunc);
+
+  /*
+   * Allow future access to aFilename by the process with the given ID.
+   */
+  void GrantFileAccess(uint32_t aProcessId, const wchar_t* aFilename,
+                       bool aPermitWrite);
+
+  /*
+   * Clears all special file access for the given process.
+   */
+  void RemovePermissionsForProcess(uint32_t aProcessId);
+
+private:
+  static sandboxing::PermissionsService* sPermissionsService;
+};
+
+} // mozilla
+
+#endif  // mozilla_sandboxing_sandboxPermissions_h
--- a/toolkit/xre/Bootstrap.h
+++ b/toolkit/xre/Bootstrap.h
@@ -26,21 +26,28 @@ void GeckoStart(JNIEnv* aEnv, char** arg
 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
 namespace sandbox {
 class BrokerServices;
 }
 #endif
 
 namespace mozilla {
 
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+namespace sandboxing {
+class PermissionsService;
+}
+#endif
+
 struct BootstrapConfig
 {
 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
   /* Chromium sandbox BrokerServices. */
   sandbox::BrokerServices* sandboxBrokerServices;
+  sandboxing::PermissionsService* sandboxPermissionsService;
 #endif
   /* Pointer to static XRE AppData from application.ini.h */
   const StaticXREAppData* appData;
   /* When the pointer above is null, points to the (string) path of an
    * application.ini file to open and parse.
    * When the pointer above is non-null, may indicate the directory where
    * application files are, relative to the XRE. */
   const char* appDataPath;
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -210,16 +210,17 @@
 #include "GeneratedJNIWrappers.h"
 #endif
 
 #if defined(MOZ_SANDBOX)
 #if defined(XP_LINUX) && !defined(ANDROID)
 #include "mozilla/SandboxInfo.h"
 #elif defined(XP_WIN)
 #include "SandboxBroker.h"
+#include "SandboxPermissions.h"
 #endif
 #endif
 
 extern uint32_t gRestartMode;
 extern void InstallSignalHandlers(const char *ProgramName);
 
 #define FILE_COMPATIBILITY_INFO NS_LITERAL_CSTRING("compatibility.ini")
 #define FILE_INVALIDATE_CACHES NS_LITERAL_CSTRING(".purgecaches")
@@ -3314,16 +3315,20 @@ XREMain::XRE_mainInit(bool* aExitFlag)
     if (BrowserTabsRemoteAutostart()) {
       MOZ_CRASH("Failed to initialize broker services, can't continue.");
     }
 #endif
     // Otherwise just warn for the moment, as most things will work.
     NS_WARNING("Failed to initialize broker services, sandboxed processes will "
                "fail to start.");
   }
+  if (mAppData->sandboxPermissionsService) {
+    SandboxPermissions::Initialize(mAppData->sandboxPermissionsService,
+                                   nullptr);
+  }
 #endif
 
 #ifdef XP_MACOSX
   // Set up ability to respond to system (Apple) events. This must occur before
   // ProcessUpdates to ensure that links clicked in external applications aren't
   // lost when updates are pending.
   SetupMacApplicationDelegate();
 
@@ -4602,16 +4607,17 @@ XREMain::XRE_main(int argc, char* argv[]
   }
 
   if (!mAppData->directory) {
     mAppData->directory = mAppData->xreDirectory;
   }
 
 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
   mAppData->sandboxBrokerServices = aConfig.sandboxBrokerServices;
+  mAppData->sandboxPermissionsService = aConfig.sandboxPermissionsService;
 #endif
 
   mozilla::IOInterposerInit ioInterposerGuard;
 
 #if defined(XP_WIN)
   // Some COM settings are global to the process and must be set before any non-
   // trivial COM is run in the application. Since these settings may affect
   // stability, we should instantiate COM ASAP so that we can ensure that these
--- a/xpcom/build/XREAppData.h
+++ b/xpcom/build/XREAppData.h
@@ -12,16 +12,21 @@
 #include "nsCOMPtr.h"
 #include "nsCRTGlue.h"
 #include "nsIFile.h"
 
 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
 namespace sandbox {
 class BrokerServices;
 }
+namespace mozilla {
+namespace sandboxing {
+class PermissionsService;
+}
+}
 #endif
 
 namespace mozilla {
 
 struct StaticXREAppData;
 
 /**
  * Application-specific data needed to start the apprunner.
@@ -189,16 +194,17 @@ public:
    */
   CharPtr UAName;
 
 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
   /**
    * Chromium sandbox BrokerServices.
    */
   sandbox::BrokerServices* sandboxBrokerServices = nullptr;
+  mozilla::sandboxing::PermissionsService* sandboxPermissionsService;
 #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/glue/XREAppData.cpp
+++ b/xpcom/glue/XREAppData.cpp
@@ -44,13 +44,14 @@ XREAppData::operator=(const XREAppData& 
   xreDirectory = aOther.xreDirectory;
   minVersion = aOther.minVersion;
   maxVersion = aOther.maxVersion;
   crashReporterURL = aOther.crashReporterURL;
   profile = aOther.profile;
   UAName = aOther.UAName;
 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
   sandboxBrokerServices = aOther.sandboxBrokerServices;
+  sandboxPermissionsService = aOther.sandboxPermissionsService;
 #endif
   return *this;
 }
 
 } // namespace mozilla