Bug 1236108: Modify sandbox initialization code to use directory service to obtain content process temp directory; r?bobowen, haik draft
authorAaron Klotz <aklotz@mozilla.com>
Tue, 08 Mar 2016 11:02:27 -0800
changeset 338188 faf03a6a45b1cfb68ba1e8f78d43b3c1af7c54dd
parent 337464 542840808172a91cf205b5e02cb573bbb962c0e8
child 338189 e08e98a99b8ea7ba34ef933033b69712f1a155e2
push id12460
push useraklotz@mozilla.com
push dateTue, 08 Mar 2016 19:04:31 +0000
reviewersbobowen, haik
bugs1236108
milestone47.0a1
Bug 1236108: Modify sandbox initialization code to use directory service to obtain content process temp directory; r?bobowen, haik The previous patch in this series creates a new directory service entry specifically for obtaining the content process temp directory. This patch converts everything else to reference that entry. It also sets appropriate environment variables in the content processes so that system APIs automatically pick up the directory. This is necessary for the crash reporter to be able to call those APIs in exception handling contexts. MozReview-Commit-ID: DF6aNKrWnWp
dom/ipc/ContentProcess.cpp
toolkit/xre/nsAppRunner.cpp
--- a/dom/ipc/ContentProcess.cpp
+++ b/dom/ipc/ContentProcess.cpp
@@ -7,18 +7,23 @@
 #include "mozilla/ipc/IOThreadChild.h"
 
 #include "ContentProcess.h"
 
 #if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
 #include "mozilla/WindowsVersion.h"
 #endif
 
+#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
+#include <stdlib.h>
+#endif
+
 #if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
 #include "mozilla/Preferences.h"
+#include "nsAppDirectoryServiceDefs.h"
 #include "nsDirectoryService.h"
 #include "nsDirectoryServiceDefs.h"
 #endif
 
 using mozilla::ipc::IOThreadChild;
 
 namespace mozilla {
 namespace dom {
@@ -28,80 +33,83 @@ static bool
 IsSandboxTempDirRequired()
 {
   // On Windows, a sandbox-writable temp directory is only used
   // for Vista or later with sandbox pref level >= 1.
   return (IsVistaOrLater() &&
     (Preferences::GetInt("security.sandbox.content.level") >= 1));
 }
 
-static const char*
-SandboxTempDirParent()
+static void
+SetTmpEnvironmentVariable(nsIFile* aValue)
 {
-  // On Windows, the sandbox-writable temp directory resides in the
-  // low integrity sandbox base directory.
-  return NS_WIN_LOW_INTEGRITY_TEMP_BASE;
+  // Save the TMP environment variable so that is is picked up by GetTempPath().
+  // Note that we specifically write to the TMP variable, as that is the first
+  // variable that is checked by GetTempPath() to determine its output.
+  nsAutoString fullTmpPath;
+  nsresult rv = aValue->GetPath(fullTmpPath);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return;
+  }
+  NS_WARN_IF(!SetEnvironmentVariableW(L"TMP", fullTmpPath.get()));
+  // We also set TEMP in case there is naughty third-party code that is
+  // referencing the environment variable directly.
+  NS_WARN_IF(!SetEnvironmentVariableW(L"TEMP", fullTmpPath.get()));
 }
 #endif
 
 #if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
 static bool
 IsSandboxTempDirRequired()
 {
   // On OSX, use the sandbox-writable temp when the pref level >= 1.
   return (Preferences::GetInt("security.sandbox.content.level") >= 1);
 }
 
-static const char*
-SandboxTempDirParent()
+static void
+SetTmpEnvironmentVariable(nsIFile* aValue)
 {
-  return NS_OS_TEMP_DIR;
+  nsAutoCString fullTmpPath;
+  nsresult rv = aValue->GetNativePath(fullTmpPath);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return;
+  }
+  NS_WARN_IF(setenv("TMPDIR", fullTmpPath.get(), 1) != 0);
 }
 #endif
 
 #if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
 static void
 SetUpSandboxEnvironment()
 {
   MOZ_ASSERT(nsDirectoryService::gService,
     "SetUpSandboxEnvironment relies on nsDirectoryService being initialized");
 
   if (!IsSandboxTempDirRequired()) {
     return;
   }
 
-  nsAdoptingString tempDirSuffix =
-    Preferences::GetString("security.sandbox.content.tempDirSuffix");
-  if (tempDirSuffix.IsEmpty()) {
-    NS_WARNING("Sandbox-writable temp directory suffix pref not set.");
-    return;
-  }
-
-  // Get the parent of our sandbox writable temp directory.
-  nsCOMPtr<nsIFile> lowIntegrityTemp;
-  nsresult rv = nsDirectoryService::gService->Get(SandboxTempDirParent(),
-                                                  NS_GET_IID(nsIFile),
-                                                  getter_AddRefs(lowIntegrityTemp));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return;
-  }
-
-  // Append our profile specific temp name.
-  rv = lowIntegrityTemp->Append(NS_LITERAL_STRING("Temp-") + tempDirSuffix);
+  nsCOMPtr<nsIFile> sandboxedContentTemp;
+  nsresult rv =
+    nsDirectoryService::gService->Get(NS_APP_CONTENT_PROCESS_TEMP_DIR,
+                                      NS_GET_IID(nsIFile),
+                                      getter_AddRefs(sandboxedContentTemp));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
   // Change the gecko defined temp directory to our sandbox-writable one.
   // Undefine returns a failure if the property is not already set.
   Unused << nsDirectoryService::gService->Undefine(NS_OS_TEMP_DIR);
-  rv = nsDirectoryService::gService->Set(NS_OS_TEMP_DIR, lowIntegrityTemp);
+  rv = nsDirectoryService::gService->Set(NS_OS_TEMP_DIR, sandboxedContentTemp);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
+
+  SetTmpEnvironmentVariable(sandboxedContentTemp);
 }
 #endif
 
 void
 ContentProcess::SetAppDir(const nsACString& aPath)
 {
   mXREEmbed.SetAppDir(aPath);
 }
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -597,47 +597,25 @@ ProcessDDE(nsINativeAppSupport* aNative,
  * @return true in all environments
 */
 static bool
 CanShowProfileManager()
 {
   return true;
 }
 
-#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
-static const char*
-SandboxTempDirParent()
-{
-  return NS_WIN_LOW_INTEGRITY_TEMP_BASE;
-}
-#endif
-
-#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
-static const char*
-SandboxTempDirParent()
-{
-  return NS_OS_TEMP_DIR;
-}
-#endif
-
 #if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
 static already_AddRefed<nsIFile>
-GetAndCleanTempDir(const nsAString& aTempDirSuffix)
+GetAndCleanTempDir()
 {
   // Get the directory within which we'll place the
   // sandbox-writable temp directory
   nsCOMPtr<nsIFile> tempDir;
-  nsresult rv = NS_GetSpecialDirectory(SandboxTempDirParent(),
-      getter_AddRefs(tempDir));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return nullptr;
-  }
-
-  // Append our profile specific temp name.
-  rv = tempDir->Append(NS_LITERAL_STRING("Temp-") + aTempDirSuffix);
+  nsresult rv = NS_GetSpecialDirectory(NS_APP_CONTENT_PROCESS_TEMP_DIR,
+                                       getter_AddRefs(tempDir));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return nullptr;
   }
 
   rv = tempDir->Remove(/* aRecursive */ true);
   if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND) {
     NS_WARNING("Failed to delete temp directory.");
     return nullptr;
@@ -708,17 +686,17 @@ SetUpSandboxEnvironment()
       // Again, if we fail to save the pref file we might not be able to clean
       // up the temp directory, so don't create one.
       NS_WARNING("Failed to save pref file, cannot create temp dir.");
       return;
     }
   }
 
   // Get (and clean up if still there) the sandbox-writable temp directory.
-  nsCOMPtr<nsIFile> tempDir = GetAndCleanTempDir(tempDirSuffix);
+  nsCOMPtr<nsIFile> tempDir = GetAndCleanTempDir();
   if (!tempDir) {
     NS_WARNING("Failed to get or clean sandboxed temp directory.");
     return;
   }
 
   rv = tempDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
@@ -730,26 +708,19 @@ CleanUpSandboxEnvironment()
 {
 #if defined(XP_WIN)
   // We can't have created the temp directory before Vista.
   if (!IsVistaOrLater()) {
     return;
   }
 #endif
 
-  // Get temp directory suffix pref.
-  nsAdoptingString tempDirSuffix =
-    Preferences::GetString("security.sandbox.content.tempDirSuffix");
-  if (tempDirSuffix.IsEmpty()) {
-    return;
-  }
-
   // Get and remove the sandbox-writable temp directory.
   // This function already warns if the deletion fails.
-  nsCOMPtr<nsIFile> tempDir = GetAndCleanTempDir(tempDirSuffix);
+  nsCOMPtr<nsIFile> tempDir = GetAndCleanTempDir();
 }
 #endif
 
 bool gSafeMode = false;
 
 /**
  * The nsXULAppInfo object implements nsIFactory so that it can be its own
  * singleton.