Bug 1336657 - On Windows add a sandbox policy rule to allow read / write access to content temp dir. r=jimm, a=gchang
authorBob Owen <bobowencode@gmail.com>
Sat, 13 May 2017 21:37:28 +0100
changeset 396321 66efefd445ba5a4d9bb084ac6dd97375ec459043
parent 396320 252e9fecd13598633ee11e26408534f378c05d14
child 396322 21648cfdecd87bce49002cbc0fee522da93494e1
push id1468
push userasasaki@mozilla.com
push dateMon, 05 Jun 2017 19:31:07 +0000
treeherdermozilla-release@0641fc6ee9d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm, gchang
bugs1336657
milestone54.0
Bug 1336657 - On Windows add a sandbox policy rule to allow read / write access to content temp dir. r=jimm, a=gchang
ipc/glue/GeckoChildProcessHost.cpp
--- a/ipc/glue/GeckoChildProcessHost.cpp
+++ b/ipc/glue/GeckoChildProcessHost.cpp
@@ -318,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
@@ -338,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
@@ -658,60 +735,16 @@ AddAppDirToCommandLine(std::vector<std::
         aCmdLine.push_back("-profile");
         aCmdLine.push_back(path.get());
       }
 #endif
     }
   }
 }
 
-#if defined(XP_WIN) && defined(MOZ_SANDBOX)
-
-static void
-AddContentSandboxAllowedFiles(int32_t aSandboxLevel,
-                              std::vector<std::wstring>& aAllowedFilesRead)
-{
-  if (aSandboxLevel < 1) {
-    return;
-  }
-
-  nsCOMPtr<nsIFile> binDir;
-  nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(binDir));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return;
-  }
-
-  nsAutoString binDirPath;
-  rv = binDir->GetPath(binDirPath);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return;
-  }
-
-  // If bin directory is on a remote drive add read access.
-  wchar_t volPath[MAX_PATH];
-  if (!::GetVolumePathNameW(binDirPath.get(), volPath, MAX_PATH)) {
-    return;
-  }
-
-  if (::GetDriveTypeW(volPath) != DRIVE_REMOTE) {
-    return;
-  }
-
-  // Convert network share path to format for sandbox policy.
-  if (Substring(binDirPath, 0, 2).Equals(L"\\\\")) {
-    binDirPath.InsertLiteral(u"??\\UNC", 1);
-  }
-
-  binDirPath.AppendLiteral(u"\\*");
-
-  aAllowedFilesRead.push_back(std::wstring(binDirPath.get()));
-}
-
-#endif
-
 bool
 GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExtraOpts, base::ProcessArchitecture arch)
 {
   // We rely on the fact that InitializeChannel() has already been processed
   // on the IO thread before this point is reached.
   if (!GetChannel()) {
     return false;
   }
@@ -1038,17 +1071,16 @@ GeckoChildProcessHost::PerformAsyncLaunc
       if (mSandboxLevel > 0 &&
           !PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX")) {
         // For now we treat every failure as fatal in SetSecurityLevelForContentProcess
         // and just crash there right away. Should this change in the future then we
         // should also handle the error here.
         mSandboxBroker.SetSecurityLevelForContentProcess(mSandboxLevel,
                                                          mPrivileges);
         shouldSandboxCurrentProcess = true;
-        AddContentSandboxAllowedFiles(mSandboxLevel, mAllowedFilesRead);
       }
 #endif // MOZ_CONTENT_SANDBOX
       break;
     case GeckoProcessType_Plugin:
       if (mSandboxLevel > 0 &&
           !PR_GetEnv("MOZ_DISABLE_NPAPI_SANDBOX")) {
         bool ok = mSandboxBroker.SetSecurityLevelForPluginProcess(mSandboxLevel);
         if (!ok) {