Bug 1018988 - Set up a low integrity temp directory when using the Windows content sandbox. r=mrbkap r=tabraldes r=froydnj
authorBob Owen <bobowencode@gmail.com>
Wed, 10 Sep 2014 12:36:17 +0100
changeset 227997 db0bf3d919b0aaed97c4332fdee5089ad9549fc8
parent 227996 07d4b55db7a37a94935c5ade41fd87a0508f8129
child 227998 b68b5511f40142fa97eb88ea725a41b53a0a577e
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmrbkap, tabraldes, froydnj
bugs1018988
milestone35.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 1018988 - Set up a low integrity temp directory when using the Windows content sandbox. r=mrbkap r=tabraldes r=froydnj
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentProcess.cpp
security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
xpcom/io/SpecialSystemDirectory.cpp
xpcom/io/SpecialSystemDirectory.h
xpcom/io/nsDirectoryService.cpp
xpcom/io/nsDirectoryServiceAtomList.h
xpcom/io/nsDirectoryServiceDefs.h
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -38,16 +38,17 @@
 #include "mozilla/layers/PCompositorChild.h"
 #include "mozilla/layers/SharedBufferManagerChild.h"
 #include "mozilla/net/NeckoChild.h"
 
 #if defined(MOZ_CONTENT_SANDBOX)
 #if defined(XP_WIN)
 #define TARGET_SANDBOX_EXPORTS
 #include "mozilla/sandboxTarget.h"
+#include "nsDirectoryServiceDefs.h"
 #elif defined(XP_LINUX)
 #include "mozilla/Sandbox.h"
 #endif
 #endif
 
 #include "mozilla/unused.h"
 
 #include "nsIConsoleListener.h"
@@ -918,16 +919,79 @@ ContentChild::AllocPImageBridgeChild(moz
 
 PBackgroundChild*
 ContentChild::AllocPBackgroundChild(Transport* aTransport,
                                     ProcessId aOtherProcess)
 {
     return BackgroundChild::Alloc(aTransport, aOtherProcess);
 }
 
+#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
+static void
+SetUpSandboxEnvironment()
+{
+    // Set up a low integrity temp directory. This only makes sense if the
+    // delayed integrity level for the content process is INTEGRITY_LEVEL_LOW.
+    nsresult rv;
+    nsCOMPtr<nsIProperties> directoryService =
+        do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+        return;
+    }
+
+    nsCOMPtr<nsIFile> lowIntegrityTemp;
+    rv = directoryService->Get(NS_WIN_LOW_INTEGRITY_TEMP, NS_GET_IID(nsIFile),
+                               getter_AddRefs(lowIntegrityTemp));
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+        return;
+    }
+
+    // Undefine returns a failure if the property is not already set.
+    unused << directoryService->Undefine(NS_OS_TEMP_DIR);
+    rv = directoryService->Set(NS_OS_TEMP_DIR, lowIntegrityTemp);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+        return;
+    }
+
+    // Set TEMP and TMP environment variables.
+    nsAutoString lowIntegrityTempPath;
+    rv = lowIntegrityTemp->GetPath(lowIntegrityTempPath);
+    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");
+}
+
+void
+ContentChild::CleanUpSandboxEnvironment()
+{
+    nsresult rv;
+    nsCOMPtr<nsIProperties> directoryService =
+        do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+        return;
+    }
+
+    nsCOMPtr<nsIFile> lowIntegrityTemp;
+    rv = directoryService->Get(NS_WIN_LOW_INTEGRITY_TEMP, NS_GET_IID(nsIFile),
+                               getter_AddRefs(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
+
 bool
 ContentChild::RecvSetProcessSandbox()
 {
     // We may want to move the sandbox initialization somewhere else
     // at some point; see bug 880808.
 #if defined(MOZ_CONTENT_SANDBOX)
 #if defined(XP_LINUX)
 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 19
@@ -942,16 +1006,17 @@ ContentChild::RecvSetProcessSandbox()
 #endif
     SetContentProcessSandbox();
 #elif defined(XP_WIN)
     nsAdoptingString contentSandboxPref =
         Preferences::GetString("browser.tabs.remote.sandbox");
     if (contentSandboxPref.EqualsLiteral("on")
         || contentSandboxPref.EqualsLiteral("warn")) {
         mozilla::SandboxTarget::Instance()->StartSandbox();
+        SetUpSandboxEnvironment();
     }
 #endif
 #endif
     return true;
 }
 
 bool
 ContentChild::RecvSpeakerManagerNotify()
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -113,16 +113,21 @@ public:
     PSharedBufferManagerChild*
     AllocPSharedBufferManagerChild(mozilla::ipc::Transport* aTransport,
                                     base::ProcessId aOtherProcess) MOZ_OVERRIDE;
 
     PImageBridgeChild*
     AllocPImageBridgeChild(mozilla::ipc::Transport* aTransport,
                            base::ProcessId aOtherProcess) MOZ_OVERRIDE;
 
+#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
+    // Cleans up any resources used by the process when sandboxed.
+    void CleanUpSandboxEnvironment();
+#endif
+
     virtual bool RecvSetProcessSandbox() MOZ_OVERRIDE;
 
     PBackgroundChild*
     AllocPBackgroundChild(Transport* aTransport, ProcessId aOtherProcess)
                           MOZ_OVERRIDE;
 
     virtual PBrowserChild* AllocPBrowserChild(const IPCTabContext& aContext,
                                               const uint32_t& aChromeFlags,
--- a/dom/ipc/ContentProcess.cpp
+++ b/dom/ipc/ContentProcess.cpp
@@ -29,13 +29,16 @@ ContentProcess::Init()
     mContent.InitXPCOM();
     
     return true;
 }
 
 void
 ContentProcess::CleanUp()
 {
+#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
+    mContent.CleanUpSandboxEnvironment();
+#endif
     mXREEmbed.Stop();
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
+++ b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
@@ -68,23 +68,26 @@ bool
 SandboxBroker::SetSecurityLevelForContentProcess(bool inWarnOnlyMode)
 {
   if (!mPolicy) {
     return false;
   }
 
   auto result = mPolicy->SetJobLevel(sandbox::JOB_NONE, 0);
   bool ret = (sandbox::SBOX_ALL_OK == result);
-  result =
-    mPolicy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
-                           sandbox::USER_RESTRICTED_SAME_ACCESS);
+
+  result = mPolicy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
+                                  sandbox::USER_RESTRICTED_SAME_ACCESS);
   ret = ret && (sandbox::SBOX_ALL_OK == result);
-  result =
-    mPolicy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
+
+  // If the delayed integrity level is changed then SetUpSandboxEnvironment and
+  // CleanUpSandboxEnvironment in ContentChild should be changed or removed.
+  result = mPolicy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
   ret = ret && (sandbox::SBOX_ALL_OK == result);
+
   result = mPolicy->SetAlternateDesktop(true);
   ret = ret && (sandbox::SBOX_ALL_OK == result);
 
   if (inWarnOnlyMode) {
     mozilla::warnonlysandbox::ApplyWarnOnlyPolicy(*mPolicy);
   }
   return ret;
 }
--- a/xpcom/io/SpecialSystemDirectory.cpp
+++ b/xpcom/io/SpecialSystemDirectory.cpp
@@ -746,16 +746,24 @@ GetSpecialSystemDirectory(SystemDirector
     }
     case Win_LocalAppdata: {
       nsresult rv = GetWindowsFolder(CSIDL_LOCAL_APPDATA, aFile);
       if (NS_FAILED(rv)) {
         rv = GetRegWindowsAppDataFolder(true, aFile);
       }
       return rv;
     }
+#if defined(MOZ_CONTENT_SANDBOX)
+    case Win_LocalAppdataLow: {
+      // This should only really fail on versions pre-Vista, in which case this
+      // shouldn't have been used in the first place.
+      GUID localAppDataLowGuid = FOLDERID_LocalAppDataLow;
+      return GetKnownFolder(&localAppDataLowGuid, aFile);
+    }
+#endif
     case Win_Documents: {
       return GetLibrarySaveToPath(CSIDL_MYDOCUMENTS,
                                   FOLDERID_DocumentsLibrary,
                                   aFile);
     }
     case Win_Pictures: {
       return GetLibrarySaveToPath(CSIDL_MYPICTURES,
                                   FOLDERID_PicturesLibrary,
--- a/xpcom/io/SpecialSystemDirectory.h
+++ b/xpcom/io/SpecialSystemDirectory.h
@@ -74,16 +74,19 @@ enum SystemDirectories {
   Win_LocalAppdata          =   228,
   Win_ProgramFiles          =   229,
   Win_Downloads             =   230,
   Win_Common_AppData        =   231,
   Win_Documents             =   232,
   Win_Pictures              =   233,
   Win_Music                 =   234,
   Win_Videos                =   235,
+#if defined(MOZ_CONTENT_SANDBOX)
+  Win_LocalAppdataLow       =   236,
+#endif
 
   Unix_LocalDirectory       =   301,
   Unix_LibDirectory         =   302,
   Unix_HomeDirectory        =   303,
   Unix_XDG_Desktop          =   304,
   Unix_XDG_Documents        =   305,
   Unix_XDG_Download         =   306,
   Unix_XDG_Music            =   307,
--- a/xpcom/io/nsDirectoryService.cpp
+++ b/xpcom/io/nsDirectoryService.cpp
@@ -19,16 +19,20 @@
 #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>
@@ -494,16 +498,57 @@ nsDirectoryService::UnregisterProvider(n
   if (!aProv) {
     return NS_ERROR_FAILURE;
   }
 
   mProviders.RemoveElement(aProv);
   return NS_OK;
 }
 
+#if defined(MOZ_CONTENT_SANDBOX) && defined(XP_WIN)
+static nsresult
+GetLowIntegrityTemp(nsIFile** aLowIntegrityTemp)
+{
+  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);
+  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;
+  }
+
+  localFile.forget(aLowIntegrityTemp);
+  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.
 
 NS_IMETHODIMP
 nsDirectoryService::GetFile(const char* aProp, bool* aPersistent,
                             nsIFile** aResult)
@@ -666,16 +711,22 @@ nsDirectoryService::GetFile(const char* 
   } else if (inAtom == nsDirectoryService::sCommon_Desktopdirectory) {
     rv = GetSpecialSystemDirectory(Win_Common_Desktopdirectory, getter_AddRefs(localFile));
   } else if (inAtom == nsDirectoryService::sCommon_AppData) {
     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));
+#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) {
     rv = GetSpecialSystemDirectory(Win_Documents, getter_AddRefs(localFile));
--- a/xpcom/io/nsDirectoryServiceAtomList.h
+++ b/xpcom/io/nsDirectoryServiceAtomList.h
@@ -66,16 +66,20 @@ DIR_ATOM(sFonts, NS_WIN_FONTS_DIR)
 DIR_ATOM(sTemplates, NS_WIN_TEMPLATES_DIR)
 DIR_ATOM(sCommon_Startmenu, NS_WIN_COMMON_STARTMENU_DIR)
 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)
+#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)
 #elif defined (XP_UNIX)
--- a/xpcom/io/nsDirectoryServiceDefs.h
+++ b/xpcom/io/nsDirectoryServiceDefs.h
@@ -115,16 +115,20 @@
   #define NS_WIN_TEMPLATES_DIR                "Tmpls"
   #define NS_WIN_COMMON_STARTMENU_DIR         "CmStrt"
   #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"
+#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.
   #define NS_WIN_DOCUMENTS_DIR                "Docs"