Bug 1162327 Part 1: Change low integrity temp to a fixed dir per profile and improve clean-up. r=jimm, r=froydnj
authorBob Owen <bobowencode@gmail.com>
Mon, 18 May 2015 11:51:07 +0100
changeset 244305 116d87a1a2a8e405fd93992dbe7aedaed82aa0f7
parent 244304 6800629ce1b1bf46220a6b215631869935750545
child 244306 ca9f095bb18cd0318938b7ebc634f27bba21a1dd
push id59897
push userbobowencode@gmail.com
push dateMon, 18 May 2015 10:55:02 +0000
treeherdermozilla-inbound@ca9f095bb18c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm, froydnj
bugs1162327
milestone41.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 1162327 Part 1: Change low integrity temp to a fixed dir per profile and improve clean-up. r=jimm, r=froydnj
browser/app/profile/firefox.js
dom/ipc/ContentProcess.cpp
toolkit/xre/nsAppRunner.cpp
xpcom/io/nsDirectoryService.cpp
xpcom/io/nsDirectoryServiceAtomList.h
xpcom/io/nsDirectoryServiceDefs.h
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1205,16 +1205,19 @@ pref("dom.ipc.plugins.sandbox-level.defa
 // 2 - a policy that we can reasonably call an effective sandbox
 // 3 - an equivalent basic policy to the Chromium renderer processes
 #if defined(NIGHTLY_BUILD)
 pref("security.sandbox.content.level", 1);
 #else
 pref("security.sandbox.content.level", 0);
 #endif
 
+// ID (a UUID when set by gecko) that is used as a per profile suffix to a low
+// integrity temp directory.
+pref("security.sandbox.content.tempDirSuffix", "");
 
 #if defined(MOZ_STACKWALKING)
 // This controls the depth of stack trace that is logged when Windows sandbox
 // logging is turned on.  This is only currently available for the content
 // process because the only other sandbox (for GMP) has too strict a policy to
 // allow stack tracing.  This does not require a restart to take effect.
 pref("security.sandbox.windows.log.stackTraceDepth", 0);
 #endif
--- a/dom/ipc/ContentProcess.cpp
+++ b/dom/ipc/ContentProcess.cpp
@@ -5,92 +5,69 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ipc/IOThreadChild.h"
 
 #include "ContentProcess.h"
 
 #if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
 #include "mozilla/Preferences.h"
+#include "mozilla/WindowsVersion.h"
 #include "nsDirectoryService.h"
 #include "nsDirectoryServiceDefs.h"
 #endif
 
 using mozilla::ipc::IOThreadChild;
 
 namespace mozilla {
 namespace dom {
 
 #if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
-static already_AddRefed<nsIFile>
-GetLowIntegrityTemp()
-{
-  MOZ_ASSERT(nsDirectoryService::gService,
-    "GetLowIntegrityTemp relies on nsDirectoryService being initialized");
-
-  // A low integrity temp only currently makes sense for sandbox pref level 1.
-  if (Preferences::GetInt("security.sandbox.content.level") != 1) {
-    return nullptr;
-  }
-
-  nsCOMPtr<nsIFile> lowIntegrityTemp;
-  nsresult rv = nsDirectoryService::gService->Get(NS_WIN_LOW_INTEGRITY_TEMP,
-                                                  NS_GET_IID(nsIFile),
-                                                  getter_AddRefs(lowIntegrityTemp));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return nullptr;
-  }
-
-  return lowIntegrityTemp.forget();
-}
-
 static void
 SetUpSandboxEnvironment()
 {
   MOZ_ASSERT(nsDirectoryService::gService,
     "SetUpSandboxEnvironment relies on nsDirectoryService being initialized");
 
-  // Setup to use a low integrity temp if available.
-  nsCOMPtr<nsIFile> lowIntegrityTemp = GetLowIntegrityTemp();
-  if (!lowIntegrityTemp) {
+  // A low integrity temp only currently makes sense for Vista or Later and
+  // sandbox pref level 1.
+  if (!IsVistaOrLater() ||
+      Preferences::GetInt("security.sandbox.content.level") != 1) {
     return;
   }
 
-  // Undefine returns a failure if the property is not already set.
-  unused << nsDirectoryService::gService->Undefine(NS_OS_TEMP_DIR);
-  nsresult rv = nsDirectoryService::gService->Set(NS_OS_TEMP_DIR, lowIntegrityTemp);
+  nsAdoptingString tempDirSuffix =
+    Preferences::GetString("security.sandbox.content.tempDirSuffix");
+  if (tempDirSuffix.IsEmpty()) {
+    NS_WARNING("Low integrity temp suffix pref not set.");
+    return;
+  }
+
+  // Get the base low integrity Mozilla temp directory.
+  nsCOMPtr<nsIFile> lowIntegrityTemp;
+  nsresult rv = nsDirectoryService::gService->Get(NS_WIN_LOW_INTEGRITY_TEMP_BASE,
+                                                  NS_GET_IID(nsIFile),
+                                                  getter_AddRefs(lowIntegrityTemp));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
-  // Set TEMP and TMP environment variables.
-  nsAutoString lowIntegrityTempPath;
-  rv = lowIntegrityTemp->GetPath(lowIntegrityTempPath);
+  // Append our profile specific temp name.
+  rv = lowIntegrityTemp->Append(NS_LITERAL_STRING("Temp-") + tempDirSuffix);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
-  bool setOK = SetEnvironmentVariableW(L"TEMP", lowIntegrityTempPath.get());
-  NS_WARN_IF_FALSE(setOK, "Failed to set TEMP to low integrity temp path");
-  setOK = SetEnvironmentVariableW(L"TMP", lowIntegrityTempPath.get());
-  NS_WARN_IF_FALSE(setOK, "Failed to set TMP to low integrity temp path");
-}
-
-static void
-CleanUpSandboxEnvironment()
-{
-  // Remove low integrity temp if it exists.
-  nsCOMPtr<nsIFile> lowIntegrityTemp = GetLowIntegrityTemp();
-  if (!lowIntegrityTemp) {
+  // Change the gecko defined temp directory to our low integrity 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);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
-
-  // Don't check the return value as the directory will only have been created
-  // if it has been used.
-  unused << lowIntegrityTemp->Remove(/* aRecursive */ true);
 }
 #endif
 
 void
 ContentProcess::SetAppDir(const nsACString& aPath)
 {
   mXREEmbed.SetAppDir(aPath);
 }
@@ -109,16 +86,13 @@ ContentProcess::Init()
 #endif
     
     return true;
 }
 
 void
 ContentProcess::CleanUp()
 {
-#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
-    CleanUpSandboxEnvironment();
-#endif
     mXREEmbed.Stop();
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -98,16 +98,20 @@
 #include <intrin.h>
 #include <math.h>
 #include "cairo/cairo-features.h"
 #include "mozilla/WindowsVersion.h"
 
 #ifndef PROCESS_DEP_ENABLE
 #define PROCESS_DEP_ENABLE 0x1
 #endif
+
+#if defined(MOZ_CONTENT_SANDBOX)
+#include "nsIUUIDGenerator.h"
+#endif
 #endif
 
 #ifdef ACCESSIBILITY
 #include "nsAccessibilityService.h"
 #if defined(XP_WIN)
 #include "mozilla/a11y/Compatibility.h"
 #endif
 #endif
@@ -578,16 +582,126 @@ ProcessDDE(nsINativeAppSupport* aNative,
  * @return true in all environments
 */
 static bool
 CanShowProfileManager()
 {
   return true;
 }
 
+#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
+static already_AddRefed<nsIFile>
+GetAndCleanLowIntegrityTemp(const nsAString& aTempDirSuffix)
+{
+  // Get the base low integrity Mozilla temp directory.
+  nsCOMPtr<nsIFile> lowIntegrityTemp;
+  nsresult rv = NS_GetSpecialDirectory(NS_WIN_LOW_INTEGRITY_TEMP_BASE,
+                                       getter_AddRefs(lowIntegrityTemp));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return nullptr;
+  }
+
+  // Append our profile specific temp name.
+  rv = lowIntegrityTemp->Append(NS_LITERAL_STRING("Temp-") + aTempDirSuffix);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return nullptr;
+  }
+
+  rv = lowIntegrityTemp->Remove(/* aRecursive */ true);
+  if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND) {
+    NS_WARNING("Failed to delete low integrity temp directory.");
+    return nullptr;
+  }
+
+  return lowIntegrityTemp.forget();
+}
+
+static void
+SetUpSandboxEnvironment()
+{
+  // A low integrity temp only currently makes sense for Vista and later, e10s
+  // and sandbox pref level 1.
+  if (!IsVistaOrLater() || !BrowserTabsRemoteAutostart() ||
+      Preferences::GetInt("security.sandbox.content.level") != 1) {
+    return;
+  }
+
+  // Get (and create if blank) temp directory suffix pref.
+  nsresult rv;
+  nsAdoptingString tempDirSuffix =
+    Preferences::GetString("security.sandbox.content.tempDirSuffix");
+  if (tempDirSuffix.IsEmpty()) {
+    nsCOMPtr<nsIUUIDGenerator> uuidgen =
+      do_GetService("@mozilla.org/uuid-generator;1", &rv);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return;
+    }
+
+    nsID uuid;
+    rv = uuidgen->GenerateUUIDInPlace(&uuid);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return;
+    }
+
+    char uuidChars[NSID_LENGTH];
+    uuid.ToProvidedString(uuidChars);
+    tempDirSuffix.AssignASCII(uuidChars);
+
+    // Save the pref to be picked up later.
+    rv = Preferences::SetCString("security.sandbox.content.tempDirSuffix",
+                                 uuidChars);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      // If we fail to save the pref we don't want to create the temp dir,
+      // because we won't be able to clean it up later.
+      return;
+    }
+
+    nsCOMPtr<nsIPrefService> prefsvc = Preferences::GetService();
+    if (!prefsvc || NS_FAILED(prefsvc->SavePrefFile(nullptr))) {
+      // 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 low integrity Mozilla temp directory.
+  nsCOMPtr<nsIFile> lowIntegrityTemp = GetAndCleanLowIntegrityTemp(tempDirSuffix);
+  if (!lowIntegrityTemp) {
+    NS_WARNING("Failed to get or clean low integrity Mozilla temp directory.");
+    return;
+  }
+
+  rv = lowIntegrityTemp->Create(nsIFile::DIRECTORY_TYPE, 0700);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return;
+  }
+}
+
+static void
+CleanUpSandboxEnvironment()
+{
+  // We can't have created a low integrity temp before Vista.
+  if (!IsVistaOrLater()) {
+    return;
+  }
+
+  // Get temp directory suffix pref.
+  nsAdoptingString tempDirSuffix =
+    Preferences::GetString("security.sandbox.content.tempDirSuffix");
+  if (tempDirSuffix.IsEmpty()) {
+    return;
+  }
+
+  // Get and remove the low integrity Mozilla temp directory.
+  // This function already warns if the deletion fails.
+  unused << GetAndCleanLowIntegrityTemp(tempDirSuffix);
+}
+#endif
+
 bool gSafeMode = false;
 
 /**
  * The nsXULAppInfo object implements nsIFactory so that it can be its own
  * singleton.
  */
 class nsXULAppInfo : public nsIXULAppInfo,
 #ifdef E10S_TESTING_ONLY
@@ -4076,24 +4190,32 @@ XREMain::XRE_mainRun()
 
 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
   if (PR_GetEnv("MOZ_INSTRUMENT_EVENT_LOOP")) {
     bool logToConsole = true;
     mozilla::InitEventTracing(logToConsole);
   }
 #endif /* MOZ_INSTRUMENT_EVENT_LOOP */
 
+#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
+  SetUpSandboxEnvironment();
+#endif
+
   {
     rv = appStartup->Run();
     if (NS_FAILED(rv)) {
       NS_ERROR("failed to run appstartup");
       gLogConsoleErrors = true;
     }
   }
 
+#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
+  CleanUpSandboxEnvironment();
+#endif
+
   return rv;
 }
 
 /*
  * XRE_main - A class based main entry point used by most platforms.
  *            Note that on OSX, aAppData->xreDirectory will point to
  *            .app/Contents/Resources.
  */
--- a/xpcom/io/nsDirectoryService.cpp
+++ b/xpcom/io/nsDirectoryService.cpp
@@ -19,20 +19,16 @@
 #include "nsISimpleEnumerator.h"
 #include "nsIStringEnumerator.h"
 
 #if defined(XP_WIN)
 #include <windows.h>
 #include <shlobj.h>
 #include <stdlib.h>
 #include <stdio.h>
-
-#if defined(MOZ_CONTENT_SANDBOX)
-#include "nsIUUIDGenerator.h"
-#endif
 #elif defined(XP_UNIX)
 #include <unistd.h>
 #include <stdlib.h>
 #include <sys/param.h>
 #include "prenv.h"
 #ifdef MOZ_WIDGET_COCOA
 #include <CoreServices/CoreServices.h>
 #include <Carbon/Carbon.h>
@@ -497,56 +493,31 @@ nsDirectoryService::UnregisterProvider(n
   }
 
   mProviders.RemoveElement(aProv);
   return NS_OK;
 }
 
 #if defined(MOZ_CONTENT_SANDBOX) && defined(XP_WIN)
 static nsresult
-GetLowIntegrityTemp(nsIFile** aLowIntegrityTemp)
+GetLowIntegrityTempBase(nsIFile** aLowIntegrityTempBase)
 {
   nsCOMPtr<nsIFile> localFile;
   nsresult rv = GetSpecialSystemDirectory(Win_LocalAppdataLow,
                                           getter_AddRefs(localFile));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  nsCOMPtr<nsIUUIDGenerator> uuidgen =
-    do_GetService("@mozilla.org/uuid-generator;1", &rv);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  nsID uuid;
-  rv = uuidgen->GenerateUUIDInPlace(&uuid);
+  rv = localFile->Append(NS_LITERAL_STRING(MOZ_USER_DIR));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  char uuidChars[NSID_LENGTH];
-  uuid.ToProvidedString(uuidChars);
-  rv = localFile->AppendNative(NS_LITERAL_CSTRING(MOZ_USER_DIR));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  rv = localFile->AppendNative(NS_LITERAL_CSTRING("MozTemp-")
-                               + nsDependentCString(uuidChars));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  rv = localFile->Create(nsIFile::DIRECTORY_TYPE, 0700);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  localFile.forget(aLowIntegrityTemp);
+  localFile.forget(aLowIntegrityTempBase);
   return rv;
 }
 #endif
 
 // DO NOT ADD ANY LOCATIONS TO THIS FUNCTION UNTIL YOU TALK TO: dougt@netscape.com.
 // This is meant to be a place of xpcom or system specific file locations, not
 // application specific locations.  If you need the later, register a callback for
 // your application.
@@ -717,18 +688,18 @@ nsDirectoryService::GetFile(const char* 
     rv = GetSpecialSystemDirectory(Win_Common_AppData, getter_AddRefs(localFile));
   } else if (inAtom == nsDirectoryService::sAppdata) {
     rv = GetSpecialSystemDirectory(Win_Appdata, getter_AddRefs(localFile));
   } else if (inAtom == nsDirectoryService::sLocalAppdata) {
     rv = GetSpecialSystemDirectory(Win_LocalAppdata, getter_AddRefs(localFile));
 #if defined(MOZ_CONTENT_SANDBOX)
   } else if (inAtom == nsDirectoryService::sLocalAppdataLow) {
     rv = GetSpecialSystemDirectory(Win_LocalAppdataLow, getter_AddRefs(localFile));
-  } else if (inAtom == nsDirectoryService::sLowIntegrityTemp) {
-    rv = GetLowIntegrityTemp(getter_AddRefs(localFile));
+  } else if (inAtom == nsDirectoryService::sLowIntegrityTempBase) {
+    rv = GetLowIntegrityTempBase(getter_AddRefs(localFile));
 #endif
   } else if (inAtom == nsDirectoryService::sPrinthood) {
     rv = GetSpecialSystemDirectory(Win_Printhood, getter_AddRefs(localFile));
   } else if (inAtom == nsDirectoryService::sWinCookiesDirectory) {
     rv = GetSpecialSystemDirectory(Win_Cookies, getter_AddRefs(localFile));
   } else if (inAtom == nsDirectoryService::sDefaultDownloadDirectory) {
     rv = GetSpecialSystemDirectory(Win_Downloads, getter_AddRefs(localFile));
   } else if (inAtom == nsDirectoryService::sDocs) {
--- a/xpcom/io/nsDirectoryServiceAtomList.h
+++ b/xpcom/io/nsDirectoryServiceAtomList.h
@@ -69,17 +69,17 @@ DIR_ATOM(sCommon_Startmenu, NS_WIN_COMMO
 DIR_ATOM(sCommon_Programs, NS_WIN_COMMON_PROGRAMS_DIR)
 DIR_ATOM(sCommon_Startup, NS_WIN_COMMON_STARTUP_DIR)
 DIR_ATOM(sCommon_Desktopdirectory, NS_WIN_COMMON_DESKTOP_DIRECTORY)
 DIR_ATOM(sCommon_AppData, NS_WIN_COMMON_APPDATA_DIR)
 DIR_ATOM(sAppdata, NS_WIN_APPDATA_DIR)
 DIR_ATOM(sLocalAppdata, NS_WIN_LOCAL_APPDATA_DIR)
 #if defined(MOZ_CONTENT_SANDBOX)
 DIR_ATOM(sLocalAppdataLow, NS_WIN_LOCAL_APPDATA_LOW_DIR)
-DIR_ATOM(sLowIntegrityTemp, NS_WIN_LOW_INTEGRITY_TEMP)
+DIR_ATOM(sLowIntegrityTempBase, NS_WIN_LOW_INTEGRITY_TEMP_BASE)
 #endif
 DIR_ATOM(sPrinthood, NS_WIN_PRINTHOOD)
 DIR_ATOM(sWinCookiesDirectory, NS_WIN_COOKIES_DIR)
 DIR_ATOM(sDefaultDownloadDirectory, NS_WIN_DEFAULT_DOWNLOAD_DIR)
 DIR_ATOM(sDocs, NS_WIN_DOCUMENTS_DIR)
 DIR_ATOM(sPictures, NS_WIN_PICTURES_DIR)
 DIR_ATOM(sMusic, NS_WIN_MUSIC_DIR)
 DIR_ATOM(sVideos, NS_WIN_VIDEOS_DIR)
--- a/xpcom/io/nsDirectoryServiceDefs.h
+++ b/xpcom/io/nsDirectoryServiceDefs.h
@@ -126,17 +126,17 @@
   #define NS_WIN_COMMON_PROGRAMS_DIR          "CmPrgs"
   #define NS_WIN_COMMON_STARTUP_DIR           "CmStrt"
   #define NS_WIN_COMMON_DESKTOP_DIRECTORY     "CmDeskP"
   #define NS_WIN_COMMON_APPDATA_DIR           "CmAppData"
   #define NS_WIN_APPDATA_DIR                  "AppData"
   #define NS_WIN_LOCAL_APPDATA_DIR            "LocalAppData"
 #if defined(MOZ_CONTENT_SANDBOX)
   #define NS_WIN_LOCAL_APPDATA_LOW_DIR        "LocalAppDataLow"
-  #define NS_WIN_LOW_INTEGRITY_TEMP           "LowTmpD"
+  #define NS_WIN_LOW_INTEGRITY_TEMP_BASE      "LowTmpDBase"
 #endif
   #define NS_WIN_PRINTHOOD                    "PrntHd"
   #define NS_WIN_COOKIES_DIR                  "CookD"
   #define NS_WIN_DEFAULT_DOWNLOAD_DIR         "DfltDwnld"
   // On Win7 and up these ids will return the default save-to location for
   // Windows Libraries associated with the specific content type. For other
   // os they return the local user folder. Note these can return network file
   // paths which can jank the ui thread so be careful how you access them.