Backed out 3 changesets (bug 1339105) for plugin process leaks a=backout
authorWes Kocher <wkocher@mozilla.com>
Mon, 22 May 2017 15:14:23 -0700
changeset 399026 f38ab8b5fba5d99cd0e618b0ae6fcfd7730acf2f
parent 399025 94218d5a75cabe7cdd91099865cb11ce7f1569ab
child 399027 054f0b1fca6319e7dc6f97678b94fc9a15752ef5
push id57
push userfmarier@mozilla.com
push dateSat, 24 Jun 2017 00:05:50 +0000
reviewersbackout
bugs1339105
milestone55.0a1
backs out431267ab28deabef6ed7c791d8dff79e3fe590c1
445875fbf13b7563fdc05437e26000e23bbdc3c2
c3fb60fbc32660719c1b8b06dc785abd4559d6c0
Backed out 3 changesets (bug 1339105) for plugin process leaks a=backout Backed out changeset 431267ab28de (bug 1339105) Backed out changeset 445875fbf13b (bug 1339105) Backed out changeset c3fb60fbc326 (bug 1339105) MozReview-Commit-ID: 4HYUQbHHnox
browser/components/migration/tests/unit/head_migration.js
dom/plugins/ipc/PluginProcessParent.cpp
ipc/glue/GeckoChildProcessHost.cpp
ipc/glue/GeckoChildProcessHost.h
js/xpconnect/src/XPCShellImpl.cpp
security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
security/sandbox/win/src/sandboxbroker/sandboxBroker.h
toolkit/xre/nsAppRunner.cpp
--- a/browser/components/migration/tests/unit/head_migration.js
+++ b/browser/components/migration/tests/unit/head_migration.js
@@ -44,30 +44,26 @@ function promiseMigration(migrator, reso
     migrator.migrate(resourceType, null, aProfile);
   });
 }
 
 /**
  * Replaces a directory service entry with a given nsIFile.
  */
 function registerFakePath(key, file) {
-  let dirsvc = Services.dirsvc.QueryInterface(Ci.nsIProperties);
-  let originalFile;
-  try {
-    // If a file is already provided save it and undefine, otherwise set will
-    // throw for persistent entries (ones that are cached).
-    originalFile = dirsvc.get(key, Ci.nsIFile);
-    dirsvc.undefine(key);
-  } catch (e) {
-    // dirsvc.get will throw if nothing provides for the key and dirsvc.undefine
-    // will throw if it's not a persistent entry, in either case we don't want
-    // to set the original file in cleanup.
-    originalFile = undefined;
-  }
-
-  dirsvc.set(key, file);
+   // Register our own provider for the Library directory.
+  let provider = {
+    getFile(prop, persistent) {
+      persistent.value = true;
+      if (prop == key) {
+        return file;
+      }
+      throw Cr.NS_ERROR_FAILURE;
+    },
+    QueryInterface: XPCOMUtils.generateQI([ Ci.nsIDirectoryServiceProvider ])
+  };
+  Services.dirsvc.QueryInterface(Ci.nsIDirectoryService)
+                 .registerProvider(provider);
   do_register_cleanup(() => {
-    dirsvc.undefine(key);
-    if (originalFile) {
-      dirsvc.set(key, originalFile);
-    }
+    Services.dirsvc.QueryInterface(Ci.nsIDirectoryService)
+                   .unregisterProvider(provider);
   });
 }
--- a/dom/plugins/ipc/PluginProcessParent.cpp
+++ b/dom/plugins/ipc/PluginProcessParent.cpp
@@ -9,16 +9,20 @@
 #include "base/string_util.h"
 #include "base/process_util.h"
 
 #include "mozilla/ipc/BrowserProcessSubThread.h"
 #include "mozilla/plugins/PluginMessageUtils.h"
 #include "mozilla/Telemetry.h"
 #include "nsThreadUtils.h"
 
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+#include "nsDirectoryServiceDefs.h"
+#endif
+
 using std::vector;
 using std::string;
 
 using mozilla::ipc::BrowserProcessSubThread;
 using mozilla::ipc::GeckoChildProcessHost;
 using mozilla::plugins::LaunchCompleteTask;
 using mozilla::plugins::PluginProcessParent;
 using base::ProcessArchitecture;
@@ -47,22 +51,92 @@ PluginProcessParent::~PluginProcessParen
         if (sPidSet->IsEmpty()) {
             delete sPidSet;
             sPidSet = nullptr;
         }
     }
 #endif
 }
 
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+static void
+AddSandboxAllowedFile(vector<std::wstring>& aAllowedFiles, nsIProperties* aDirSvc,
+                      const char* aDir, const nsAString& aSuffix = EmptyString())
+{
+    nsCOMPtr<nsIFile> userDir;
+    nsresult rv = aDirSvc->Get(aDir, NS_GET_IID(nsIFile), getter_AddRefs(userDir));
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+        return;
+    }
+
+    nsAutoString userDirPath;
+    rv = userDir->GetPath(userDirPath);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+        return;
+    }
+
+    if (!aSuffix.IsEmpty()) {
+        userDirPath.Append(aSuffix);
+    }
+    aAllowedFiles.push_back(std::wstring(userDirPath.get()));
+    return;
+}
+
+static void
+AddSandboxAllowedFiles(int32_t aSandboxLevel,
+                       vector<std::wstring>& aAllowedFilesRead,
+                       vector<std::wstring>& aAllowedFilesReadWrite,
+                       vector<std::wstring>& aAllowedDirectories)
+{
+    if (aSandboxLevel < 2) {
+        return;
+    }
+
+    nsresult rv;
+    nsCOMPtr<nsIProperties> dirSvc =
+        do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+        return;
+    }
+
+    // Level 2 and above is now using low integrity, so we need to give write
+    // access to the Flash directories.
+    // This should be made Flash specific (Bug 1171396).
+    AddSandboxAllowedFile(aAllowedFilesReadWrite, dirSvc, NS_WIN_APPDATA_DIR,
+                          NS_LITERAL_STRING("\\Macromedia\\Flash Player\\*"));
+    AddSandboxAllowedFile(aAllowedFilesReadWrite, dirSvc, NS_WIN_LOCAL_APPDATA_DIR,
+                          NS_LITERAL_STRING("\\Macromedia\\Flash Player\\*"));
+    AddSandboxAllowedFile(aAllowedFilesReadWrite, dirSvc, NS_WIN_APPDATA_DIR,
+                          NS_LITERAL_STRING("\\Adobe\\Flash Player\\*"));
+
+    // Access also has to be given to create the parent directories as they may
+    // not exist.
+    AddSandboxAllowedFile(aAllowedDirectories, dirSvc, NS_WIN_APPDATA_DIR,
+                          NS_LITERAL_STRING("\\Macromedia"));
+    AddSandboxAllowedFile(aAllowedDirectories, dirSvc, NS_WIN_APPDATA_DIR,
+                          NS_LITERAL_STRING("\\Macromedia\\Flash Player"));
+    AddSandboxAllowedFile(aAllowedDirectories, dirSvc, NS_WIN_LOCAL_APPDATA_DIR,
+                          NS_LITERAL_STRING("\\Macromedia"));
+    AddSandboxAllowedFile(aAllowedDirectories, dirSvc, NS_WIN_LOCAL_APPDATA_DIR,
+                          NS_LITERAL_STRING("\\Macromedia\\Flash Player"));
+    AddSandboxAllowedFile(aAllowedDirectories, dirSvc, NS_WIN_APPDATA_DIR,
+                          NS_LITERAL_STRING("\\Adobe"));
+    AddSandboxAllowedFile(aAllowedDirectories, dirSvc, NS_WIN_APPDATA_DIR,
+                          NS_LITERAL_STRING("\\Adobe\\Flash Player"));
+}
+#endif
+
 bool
 PluginProcessParent::Launch(mozilla::UniquePtr<LaunchCompleteTask> aLaunchCompleteTask,
                             int32_t aSandboxLevel)
 {
 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
     mSandboxLevel = aSandboxLevel;
+    AddSandboxAllowedFiles(mSandboxLevel, mAllowedFilesRead,
+                           mAllowedFilesReadWrite, mAllowedDirectories);
 #else
     if (aSandboxLevel != 0) {
         MOZ_ASSERT(false,
                    "Can't enable an NPAPI process sandbox for platform/build.");
     }
 #endif
 
     ProcessArchitecture currentArchitecture = base::GetCurrentProcessArchitecture();
--- a/ipc/glue/GeckoChildProcessHost.cpp
+++ b/ipc/glue/GeckoChildProcessHost.cpp
@@ -18,17 +18,17 @@
 #include "SharedMemoryBasic.h"
 #endif
 
 #include "MainThreadUtils.h"
 #include "mozilla/Sprintf.h"
 #include "prenv.h"
 #include "nsXPCOMPrivate.h"
 
-#if defined(MOZ_CONTENT_SANDBOX) && defined(XP_MACOSX)
+#if defined(MOZ_CONTENT_SANDBOX)
 #include "nsAppDirectoryServiceDefs.h"
 #endif
 
 #include "nsExceptionHandler.h"
 
 #include "nsDirectoryServiceDefs.h"
 #include "nsIFile.h"
 #include "nsPrintfCString.h"
@@ -43,16 +43,17 @@
 #ifdef XP_WIN
 #include "nsIWinTaskbar.h"
 #include <stdlib.h>
 #define NS_TASKBAR_CONTRACTID "@mozilla.org/windows-taskbar;1"
 
 #if defined(MOZ_SANDBOX)
 #include "mozilla/Preferences.h"
 #include "mozilla/sandboxing/sandboxLogging.h"
+#include "nsDirectoryServiceUtils.h"
 #endif
 #endif
 
 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
 #include "mozilla/SandboxReporter.h"
 #endif
 
 #include "nsTArray.h"
@@ -106,16 +107,44 @@ GeckoChildProcessHost::GeckoChildProcess
     mSandboxLevel(0),
 #endif
     mChildProcessHandle(0)
 #if defined(MOZ_WIDGET_COCOA)
   , mChildTask(MACH_PORT_NULL)
 #endif
 {
     MOZ_COUNT_CTOR(GeckoChildProcessHost);
+
+#if defined(OS_WIN) && defined(MOZ_CONTENT_SANDBOX)
+    // Add $PROFILE/chrome to the white list because it may located on network
+    // drive.
+    if (mProcessType == GeckoProcessType_Content) {
+        nsCOMPtr<nsIProperties> directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
+        NS_ASSERTION(directoryService, "Expected XPCOM to be available");
+        if (directoryService) {
+            // Full path to the profile dir
+            nsCOMPtr<nsIFile> profileDir;
+            nsresult rv = directoryService->Get(NS_APP_USER_PROFILE_50_DIR,
+                                                NS_GET_IID(nsIFile),
+                                                getter_AddRefs(profileDir));
+            if (NS_SUCCEEDED(rv)) {
+                profileDir->Append(NS_LITERAL_STRING("chrome"));
+                profileDir->Append(NS_LITERAL_STRING("*"));
+                nsAutoCString path;
+                MOZ_ALWAYS_SUCCEEDS(profileDir->GetNativePath(path));
+                std::wstring wpath = UTF8ToWide(path.get());
+                // If the patch starts with "\\\\", it is a UNC path.
+                if (wpath.find(L"\\\\") == 0) {
+                    wpath.insert(1, L"??\\UNC");
+                }
+                mAllowedFilesRead.push_back(wpath);
+            }
+        }
+    }
+#endif
 }
 
 GeckoChildProcessHost::~GeckoChildProcessHost()
 
 {
   AssertIOThread();
 
   MOZ_COUNT_DTOR(GeckoChildProcessHost);
@@ -289,16 +318,88 @@ uint32_t GeckoChildProcessHost::sNextUni
 
 /* static */
 uint32_t
 GeckoChildProcessHost::GetUniqueID()
 {
   return sNextUniqueID++;
 }
 
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+
+// This is pretty much a duplicate of the function in PluginProcessParent.
+// Simply copying for now due to uplift. I will address this duplication and for
+// example the similar code in the Constructor in bug 1339105.
+static void
+AddSandboxAllowedFile(std::vector<std::wstring>& aAllowedFiles,
+                      nsIProperties* aDirSvc, const char* aDirKey,
+                      const nsAString& aSuffix = EmptyString())
+{
+  nsCOMPtr<nsIFile> ruleDir;
+  nsresult rv =
+    aDirSvc->Get(aDirKey, NS_GET_IID(nsIFile), getter_AddRefs(ruleDir));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return;
+  }
+
+  nsAutoString rulePath;
+  rv = ruleDir->GetPath(rulePath);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return;
+  }
+
+  // Convert network share path to format for sandbox policy.
+  if (Substring(rulePath, 0, 2).Equals(L"\\\\")) {
+    rulePath.InsertLiteral(u"??\\UNC", 1);
+  }
+
+  if (!aSuffix.IsEmpty()) {
+    rulePath.Append(aSuffix);
+  }
+
+  aAllowedFiles.push_back(std::wstring(rulePath.get()));
+  return;
+}
+
+static void
+AddContentSandboxAllowedFiles(int32_t aSandboxLevel,
+                              std::vector<std::wstring>& aAllowedFilesRead,
+                              std::vector<std::wstring>& aAllowedFilesReadWrite)
+{
+  if (aSandboxLevel < 1) {
+    return;
+  }
+
+  nsresult rv;
+  nsCOMPtr<nsIProperties> dirSvc =
+    do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return;
+  }
+
+  // Add rule to allow read / write access to content temp dir. If for some
+  // reason the addition of the content temp failed, this will give write access
+  // to the normal TEMP dir. However such failures should be pretty rare and
+  // without this printing will not currently work.
+  AddSandboxAllowedFile(aAllowedFilesReadWrite, dirSvc,
+                        NS_APP_CONTENT_PROCESS_TEMP_DIR,
+                        NS_LITERAL_STRING("\\*"));
+
+  if (aSandboxLevel < 2) {
+    return;
+  }
+
+  // Add rule to allow read access to installation directory. At less than
+  // level 2 we already add a global read rule.
+  AddSandboxAllowedFile(aAllowedFilesRead, dirSvc, NS_GRE_DIR,
+                        NS_LITERAL_STRING("\\*"));
+}
+
+#endif
+
 void
 GeckoChildProcessHost::PrepareLaunch()
 {
 #ifdef MOZ_CRASHREPORTER
   if (CrashReporter::GetEnabled()) {
     CrashReporter::OOPInit();
   }
 #endif
@@ -309,16 +410,21 @@ GeckoChildProcessHost::PrepareLaunch()
   }
 
 #if defined(MOZ_CONTENT_SANDBOX)
   // We need to get the pref here as the process is launched off main thread.
   if (mProcessType == GeckoProcessType_Content) {
     mSandboxLevel = Preferences::GetInt("security.sandbox.content.level");
     mEnableSandboxLogging =
       Preferences::GetBool("security.sandbox.logging.enabled");
+
+    // This calls the directory service, which can also cause issues if called
+    // off main thread.
+    AddContentSandboxAllowedFiles(mSandboxLevel, mAllowedFilesRead,
+                                  mAllowedFilesReadWrite);
   }
 #endif
 
 #if defined(MOZ_SANDBOX)
   // For other process types we can't rely on them being launched on main
   // thread and they may not have access to prefs in the child process, so allow
   // them to turn on logging via an environment variable.
   mEnableSandboxLogging = mEnableSandboxLogging
@@ -1023,16 +1129,28 @@ GeckoChildProcessHost::PerformAsyncLaunc
   };
 
   if (shouldSandboxCurrentProcess) {
     for (auto it = mAllowedFilesRead.begin();
          it != mAllowedFilesRead.end();
          ++it) {
       mSandboxBroker.AllowReadFile(it->c_str());
     }
+
+    for (auto it = mAllowedFilesReadWrite.begin();
+         it != mAllowedFilesReadWrite.end();
+         ++it) {
+      mSandboxBroker.AllowReadWriteFile(it->c_str());
+    }
+
+    for (auto it = mAllowedDirectories.begin();
+         it != mAllowedDirectories.end();
+         ++it) {
+      mSandboxBroker.AllowDirectory(it->c_str());
+    }
   }
 #endif // XP_WIN && MOZ_SANDBOX
 
   // Add the application directory path (-appdir path)
   AddAppDirToCommandLine(cmdLine);
 
   // XXX Command line params past this point are expected to be at
   // the end of the command line string, and in a specific order.
--- a/ipc/glue/GeckoChildProcessHost.h
+++ b/ipc/glue/GeckoChildProcessHost.h
@@ -152,16 +152,18 @@ protected:
 
 #ifdef XP_WIN
   void InitWindowsGroupID();
   nsString mGroupId;
 
 #ifdef MOZ_SANDBOX
   SandboxBroker mSandboxBroker;
   std::vector<std::wstring> mAllowedFilesRead;
+  std::vector<std::wstring> mAllowedFilesReadWrite;
+  std::vector<std::wstring> mAllowedDirectories;
   bool mEnableSandboxLogging;
   int32_t mSandboxLevel;
 #endif
 #endif // XP_WIN
 
 #if defined(OS_POSIX)
   base::file_handle_mapping_vector mFileMap;
 #endif
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -1457,17 +1457,16 @@ XRE_XPCShellMain(int argc, char** argv, 
         // Plugin may require audio session if installed plugin can initialize
         // asynchronized.
         AutoAudioSession audioSession;
 
 #if defined(MOZ_SANDBOX)
         // Required for sandboxed child processes.
         if (aShellData->sandboxBrokerServices) {
           SandboxBroker::Initialize(aShellData->sandboxBrokerServices);
-          SandboxBroker::CacheRulesDirectories();
         } else {
           NS_WARNING("Failed to initialize broker services, sandboxed "
                      "processes will fail to start.");
         }
 #endif
 #endif
 
         {
--- a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
+++ b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
@@ -3,100 +3,38 @@
 /* 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 "mozilla/ClearOnShutdown.h"
 #include "mozilla/Logging.h"
 #include "mozilla/NSPRLogModulesParser.h"
-#include "mozilla/UniquePtr.h"
-#include "nsAppDirectoryServiceDefs.h"
-#include "nsCOMPtr.h"
-#include "nsDirectoryServiceDefs.h"
-#include "nsIFile.h"
-#include "nsIProperties.h"
-#include "nsServiceManagerUtils.h"
-#include "nsString.h"
 #include "sandbox/win/src/sandbox.h"
 #include "sandbox/win/src/security_level.h"
 
 namespace mozilla
 {
 
 sandbox::BrokerServices *SandboxBroker::sBrokerService = nullptr;
 
-// Cached special directories used for adding policy rules.
-static UniquePtr<nsString> sBinDir;
-static UniquePtr<nsString> sProfileDir;
-static UniquePtr<nsString> sContentTempDir;
-static UniquePtr<nsString> sRoamingAppDataDir;
-static UniquePtr<nsString> sLocalAppDataDir;
-
 static LazyLogModule sSandboxBrokerLog("SandboxBroker");
 
 #define LOG_E(...) MOZ_LOG(sSandboxBrokerLog, LogLevel::Error, (__VA_ARGS__))
 #define LOG_W(...) MOZ_LOG(sSandboxBrokerLog, LogLevel::Warning, (__VA_ARGS__))
 
 /* static */
 void
 SandboxBroker::Initialize(sandbox::BrokerServices* aBrokerServices)
 {
   sBrokerService = aBrokerServices;
 }
 
-static void
-CacheDirAndAutoClear(nsIProperties* aDirSvc, const char* aDirKey,
-                     UniquePtr<nsString>* cacheVar)
-{
-  nsCOMPtr<nsIFile> dirToCache;
-  nsresult rv =
-    aDirSvc->Get(aDirKey, NS_GET_IID(nsIFile), getter_AddRefs(dirToCache));
-  if (NS_FAILED(rv)) {
-    // This can only be an NS_WARNING, because it can fail for xpcshell tests.
-    NS_WARNING("Failed to get directory to cache.");
-    LOG_E("Failed to get directory to cache, key: %s.", aDirKey);
-    return;
-  }
-
-  *cacheVar = MakeUnique<nsString>();
-  ClearOnShutdown(cacheVar);
-  MOZ_ALWAYS_SUCCEEDS(dirToCache->GetPath(**cacheVar));
-
-  // Convert network share path to format for sandbox policy.
-  if (Substring(**cacheVar, 0, 2).Equals(L"\\\\")) {
-    (*cacheVar)->InsertLiteral(u"??\\UNC", 1);
-  }
-}
-
-/* static */
-void
-SandboxBroker::CacheRulesDirectories()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  nsresult rv;
-  nsCOMPtr<nsIProperties> dirSvc =
-    do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
-  if (NS_FAILED(rv)) {
-    MOZ_ASSERT(false, "Failed to get directory service, cannot cache directories for rules.");
-    LOG_E("Failed to get directory service, cannot cache directories for rules.");
-    return;
-  }
-
-  CacheDirAndAutoClear(dirSvc, NS_GRE_DIR, &sBinDir);
-  CacheDirAndAutoClear(dirSvc, NS_APP_USER_PROFILE_50_DIR, &sProfileDir);
-  CacheDirAndAutoClear(dirSvc, NS_APP_CONTENT_PROCESS_TEMP_DIR, &sContentTempDir);
-  CacheDirAndAutoClear(dirSvc, NS_WIN_APPDATA_DIR, &sRoamingAppDataDir);
-  CacheDirAndAutoClear(dirSvc, NS_WIN_LOCAL_APPDATA_DIR, &sLocalAppDataDir);
-}
-
 SandboxBroker::SandboxBroker()
 {
   if (sBrokerService) {
     mPolicy = sBrokerService->CreatePolicy();
   } else {
     mPolicy = nullptr;
   }
 }
@@ -190,45 +128,17 @@ SandboxBroker::LaunchApp(const wchar_t *
   CloseHandle(targetInfo.hThread);
 
   // Return the process handle to the caller
   *aProcessHandle = targetInfo.hProcess;
 
   return true;
 }
 
-static void
-AddCachedDirRule(sandbox::TargetPolicy* aPolicy,
-                 sandbox::TargetPolicy::Semantics aAccess,
-                 const UniquePtr<nsString>& aBaseDir,
-                 const nsLiteralString& aRelativePath)
-{
-  if (!aBaseDir) {
-    // This can only be an NS_WARNING, because it can null for xpcshell tests.
-    NS_WARNING("Tried to add rule with null base dir.");
-    LOG_E("Tried to add rule with null base dir. Relative path: %S, Access: %d",
-          aRelativePath.get(), aAccess);
-    return;
-  }
-
-  nsAutoString rulePath(*aBaseDir);
-  rulePath.Append(aRelativePath);
-
-  sandbox::ResultCode result =
-    aPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, aAccess,
-                     rulePath.get());
-  if (sandbox::SBOX_ALL_OK != result) {
-    NS_ERROR("Failed to add file policy rule.");
-    LOG_E("Failed (ResultCode %d) to add %d access to: %S",
-          result, aAccess, rulePath.get());
-  }
-}
-
 #if defined(MOZ_CONTENT_SANDBOX)
-
 void
 SandboxBroker::SetSecurityLevelForContentProcess(int32_t aSandboxLevel,
                                                  base::ChildPrivileges aPrivs)
 {
   MOZ_RELEASE_ASSERT(mPolicy, "mPolicy must be set before this call.");
 
   sandbox::JobLevel jobLevel;
   sandbox::TokenLevel accessTokenLevel;
@@ -244,22 +154,17 @@ SandboxBroker::SetSecurityLevelForConten
     accessTokenLevel = sandbox::USER_LOCKDOWN;
     initialIntegrityLevel = sandbox::INTEGRITY_LEVEL_LOW;
     delayedIntegrityLevel = sandbox::INTEGRITY_LEVEL_UNTRUSTED;
   } else if (aSandboxLevel >= 10) {
     jobLevel = sandbox::JOB_RESTRICTED;
     accessTokenLevel = sandbox::USER_LIMITED;
     initialIntegrityLevel = sandbox::INTEGRITY_LEVEL_LOW;
     delayedIntegrityLevel = sandbox::INTEGRITY_LEVEL_LOW;
-  } else if (aSandboxLevel >= 3) {
-    jobLevel = sandbox::JOB_RESTRICTED;
-    accessTokenLevel = sandbox::USER_LIMITED;
-    initialIntegrityLevel = sandbox::INTEGRITY_LEVEL_LOW;
-    delayedIntegrityLevel = sandbox::INTEGRITY_LEVEL_LOW;
-  } else if (aSandboxLevel == 2) {
+  } else if (aSandboxLevel >= 2) {
     jobLevel = sandbox::JOB_INTERACTIVE;
     accessTokenLevel = sandbox::USER_INTERACTIVE;
     initialIntegrityLevel = sandbox::INTEGRITY_LEVEL_LOW;
     delayedIntegrityLevel = sandbox::INTEGRITY_LEVEL_LOW;
   } else if (aSandboxLevel == 1) {
     jobLevel = sandbox::JOB_NONE;
     accessTokenLevel = sandbox::USER_NON_ADMIN;
     initialIntegrityLevel = sandbox::INTEGRITY_LEVEL_LOW;
@@ -294,17 +199,17 @@ SandboxBroker::SetSecurityLevelForConten
 
   result = mPolicy->SetIntegrityLevel(initialIntegrityLevel);
   MOZ_RELEASE_ASSERT(sandbox::SBOX_ALL_OK == result,
                      "SetIntegrityLevel should never fail, what happened?");
   result = mPolicy->SetDelayedIntegrityLevel(delayedIntegrityLevel);
   MOZ_RELEASE_ASSERT(sandbox::SBOX_ALL_OK == result,
                      "SetDelayedIntegrityLevel should never fail, what happened?");
 
-  if (aSandboxLevel > 3) {
+  if (aSandboxLevel > 2) {
     result = mPolicy->SetAlternateDesktop(true);
     MOZ_RELEASE_ASSERT(sandbox::SBOX_ALL_OK == result,
                        "Failed to create alternate desktop for sandbox.");
   }
 
   sandbox::MitigationFlags mitigations =
     sandbox::MITIGATION_BOTTOM_UP_ASLR |
     sandbox::MITIGATION_HEAP_TERMINATE |
@@ -319,44 +224,25 @@ SandboxBroker::SetSecurityLevelForConten
   mitigations =
     sandbox::MITIGATION_STRICT_HANDLE_CHECKS |
     sandbox::MITIGATION_DLL_SEARCH_ORDER;
 
   result = mPolicy->SetDelayedProcessMitigations(mitigations);
   MOZ_RELEASE_ASSERT(sandbox::SBOX_ALL_OK == result,
                      "Invalid flags for SetDelayedProcessMitigations.");
 
-  // Add rule to allow read / write access to content temp dir. If for some
-  // reason the addition of the content temp failed, this will give write access
-  // to the normal TEMP dir. However such failures should be pretty rare and
-  // without this printing will not currently work.
-  AddCachedDirRule(mPolicy, sandbox::TargetPolicy::FILES_ALLOW_ANY,
-                   sContentTempDir, NS_LITERAL_STRING("\\*"));
-
   // We still have edge cases where the child at low integrity can't read some
   // files, so add a rule to allow read access to everything when required.
   if (aSandboxLevel == 1 ||
       aPrivs == base::ChildPrivileges::PRIVILEGES_FILEREAD) {
     result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
                               sandbox::TargetPolicy::FILES_ALLOW_READONLY,
                               L"*");
     MOZ_RELEASE_ASSERT(sandbox::SBOX_ALL_OK == result,
                        "With these static arguments AddRule should never fail, what happened?");
-  } else {
-    // Add rule to allow read access to installation directory.
-    AddCachedDirRule(mPolicy, sandbox::TargetPolicy::FILES_ALLOW_READONLY,
-                     sBinDir, NS_LITERAL_STRING("\\*"));
-
-    // Add rule to allow read access chrome directory within profile.
-    AddCachedDirRule(mPolicy, sandbox::TargetPolicy::FILES_ALLOW_READONLY,
-                     sProfileDir, NS_LITERAL_STRING("\\chrome\\*"));
-
-    // Add rule to allow read access extensions directory within profile.
-    AddCachedDirRule(mPolicy, sandbox::TargetPolicy::FILES_ALLOW_READONLY,
-                     sProfileDir, NS_LITERAL_STRING("\\extensions\\*"));
   }
 
   // Add the policy for the client side of a pipe. It is just a file
   // in the \pipe\ namespace. We restrict it to pipes that start with
   // "chrome." so the sandboxed process cannot connect to system services.
   result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
                             sandbox::TargetPolicy::FILES_ALLOW_ANY,
                             L"\\??\\pipe\\chrome.*");
@@ -564,51 +450,16 @@ SandboxBroker::SetSecurityLevelForPlugin
     sandbox::MITIGATION_SEHOP |
     sandbox::MITIGATION_DEP_NO_ATL_THUNK |
     sandbox::MITIGATION_DEP;
 
   result = mPolicy->SetProcessMitigations(mitigations);
   SANDBOX_ENSURE_SUCCESS(result,
                          "Invalid flags for SetProcessMitigations.");
 
-  if (aSandboxLevel >= 2) {
-    // Level 2 and above uses low integrity, so we need to give write access to
-    // the Flash directories.
-    AddCachedDirRule(mPolicy, sandbox::TargetPolicy::FILES_ALLOW_ANY,
-                     sRoamingAppDataDir,
-                     NS_LITERAL_STRING("\\Macromedia\\Flash Player\\*"));
-    AddCachedDirRule(mPolicy, sandbox::TargetPolicy::FILES_ALLOW_ANY,
-                     sLocalAppDataDir,
-                     NS_LITERAL_STRING("\\Macromedia\\Flash Player\\*"));
-    AddCachedDirRule(mPolicy, sandbox::TargetPolicy::FILES_ALLOW_ANY,
-                     sRoamingAppDataDir,
-                     NS_LITERAL_STRING("\\Adobe\\Flash Player\\*"));
-
-    // Access also has to be given to create the parent directories as they may
-    // not exist.
-    AddCachedDirRule(mPolicy, sandbox::TargetPolicy::FILES_ALLOW_DIR_ANY,
-                     sRoamingAppDataDir,
-                     NS_LITERAL_STRING("\\Macromedia"));
-    AddCachedDirRule(mPolicy, sandbox::TargetPolicy::FILES_ALLOW_DIR_ANY,
-                     sRoamingAppDataDir,
-                     NS_LITERAL_STRING("\\Macromedia\\Flash Player"));
-    AddCachedDirRule(mPolicy, sandbox::TargetPolicy::FILES_ALLOW_DIR_ANY,
-                     sLocalAppDataDir,
-                     NS_LITERAL_STRING("\\Macromedia"));
-    AddCachedDirRule(mPolicy, sandbox::TargetPolicy::FILES_ALLOW_DIR_ANY,
-                     sLocalAppDataDir,
-                     NS_LITERAL_STRING("\\Macromedia\\Flash Player"));
-    AddCachedDirRule(mPolicy, sandbox::TargetPolicy::FILES_ALLOW_DIR_ANY,
-                     sRoamingAppDataDir,
-                     NS_LITERAL_STRING("\\Adobe"));
-    AddCachedDirRule(mPolicy, sandbox::TargetPolicy::FILES_ALLOW_DIR_ANY,
-                     sRoamingAppDataDir,
-                     NS_LITERAL_STRING("\\Adobe\\Flash Player"));
-  }
-
   // Add the policy for the client side of a pipe. It is just a file
   // in the \pipe\ namespace. We restrict it to pipes that start with
   // "chrome." so the sandboxed process cannot connect to system services.
   result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
                             sandbox::TargetPolicy::FILES_ALLOW_ANY,
                             L"\\??\\pipe\\chrome.*");
   SANDBOX_ENSURE_SUCCESS(result,
                          "With these static arguments AddRule should never fail, what happened?");
@@ -630,16 +481,23 @@ SandboxBroker::SetSecurityLevelForPlugin
                          "With these static arguments AddRule should never fail, what happened?");
 
   result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES,
                             sandbox::TargetPolicy::HANDLES_DUP_BROKER,
                             L"Section");
   SANDBOX_ENSURE_SUCCESS(result,
                          "With these static arguments AddRule should never fail, what happened?");
 
+  // The following is required for the Java plugin.
+  result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
+                            sandbox::TargetPolicy::FILES_ALLOW_ANY,
+                            L"\\??\\pipe\\jpi2_pid*_pipe*");
+  SANDBOX_ENSURE_SUCCESS(result,
+                         "With these static arguments AddRule should never fail, what happened?");
+
   // These register keys are used by the file-browser dialog box.  They
   // remember the most-recently-used folders.
   result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_REGISTRY,
                             sandbox::TargetPolicy::REG_ALLOW_ANY,
                             L"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\OpenSavePidlMRU\\*");
   SANDBOX_ENSURE_SUCCESS(result,
                          "With these static arguments AddRule should never fail, what happened?");
 
@@ -826,16 +684,55 @@ SandboxBroker::AllowReadFile(wchar_t con
     LOG_E("Failed (ResultCode %d) to add read access to: %S", result, file);
     return false;
   }
 
   return true;
 }
 
 bool
+SandboxBroker::AllowReadWriteFile(wchar_t const *file)
+{
+  if (!mPolicy) {
+    return false;
+  }
+
+  auto result =
+    mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
+                     sandbox::TargetPolicy::FILES_ALLOW_ANY,
+                     file);
+  if (sandbox::SBOX_ALL_OK != result) {
+    LOG_E("Failed (ResultCode %d) to add read/write access to: %S",
+          result, file);
+    return false;
+  }
+
+  return true;
+}
+
+bool
+SandboxBroker::AllowDirectory(wchar_t const *dir)
+{
+  if (!mPolicy) {
+    return false;
+  }
+
+  auto result =
+    mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
+                     sandbox::TargetPolicy::FILES_ALLOW_DIR_ANY,
+                     dir);
+  if (sandbox::SBOX_ALL_OK != result) {
+    LOG_E("Failed (ResultCode %d) to add directory access to: %S", result, dir);
+    return false;
+  }
+
+  return true;
+}
+
+bool
 SandboxBroker::AddTargetPeer(HANDLE aPeerProcess)
 {
   if (!sBrokerService) {
     return false;
   }
 
   sandbox::ResultCode result = sBrokerService->AddTargetPeer(aPeerProcess);
   return (sandbox::SBOX_ALL_OK == result);
--- a/security/sandbox/win/src/sandboxbroker/sandboxBroker.h
+++ b/security/sandbox/win/src/sandboxbroker/sandboxBroker.h
@@ -21,22 +21,16 @@ namespace mozilla {
 
 class SandboxBroker
 {
 public:
   SandboxBroker();
 
   static void Initialize(sandbox::BrokerServices* aBrokerServices);
 
-  /**
-   * Cache directory paths for use in policy rules. Must be called on main
-   * thread.
-   */
-  static void CacheRulesDirectories();
-
   bool LaunchApp(const wchar_t *aPath,
                  const wchar_t *aArguments,
                  const bool aEnableLogging,
                  void **aProcessHandle);
   virtual ~SandboxBroker();
 
   // Security levels for different types of processes
 #if defined(MOZ_CONTENT_SANDBOX)
@@ -50,16 +44,18 @@ public:
   enum SandboxLevel {
     LockDown,
     Restricted
   };
   bool SetSecurityLevelForGMPlugin(SandboxLevel aLevel);
 
   // 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();
 
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -4436,20 +4436,16 @@ XREMain::XRE_mainRun()
   // in that it comes from a different CRT (firefox.exe's static-linked copy).
   // Ugly details in http://bugzil.la/1175039#c27
   char appFile[MAX_PATH];
   if (GetEnvironmentVariableA("XUL_APP_FILE", appFile, sizeof(appFile))) {
     SmprintfPointer saved = mozilla::Smprintf("XUL_APP_FILE=%s", appFile);
     // We intentionally leak the string here since it is required by PR_SetEnv.
     PR_SetEnv(saved.release());
   }
-
-  // Call SandboxBroker to cache directories needed for policy rules, this must
-  // be called after mDirProvider.DoStartup as it needs the profile dir.
-  SandboxBroker::CacheRulesDirectories();
 #endif
 
   SaveStateForAppInitiatedRestart();
 
   // clear out any environment variables which may have been set
   // during the relaunch process now that we know we won't be relaunching.
   SaveToEnv("XRE_PROFILE_PATH=");
   SaveToEnv("XRE_PROFILE_LOCAL_PATH=");