Bug 1361733 - In debug builds, do not allow content sandbox to write to all of /private/var r=haik
authorAlex Gaynor <agaynor@mozilla.com>
Tue, 02 May 2017 11:07:10 -0400
changeset 357136 45cc3ebc04466d66cf3895aeefef65f8562ae010
parent 357135 b230bcb04a19ac2bd921a2b84e9262b391d0991d
child 357137 40407595770084926447edba12343c2da2f21bd3
push id31783
push usercbook@mozilla.com
push dateTue, 09 May 2017 12:03:48 +0000
treeherdermozilla-central@b0ff0c5c0a35 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershaik
bugs1361733
milestone55.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 1361733 - In debug builds, do not allow content sandbox to write to all of /private/var r=haik This permission was needed for the memory bloat logging, which is used for leaktest, including logging intentionally crashing processes. Now we restrict ourselves to only allowing writes to the location needed for this logging, rather than all of /private/var. MozReview-Commit-ID: 5AbJEZlDHNV
dom/ipc/ContentChild.cpp
security/sandbox/mac/Sandbox.h
security/sandbox/mac/Sandbox.mm
security/sandbox/mac/SandboxPolicies.h
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -1274,16 +1274,40 @@ GetAppPaths(nsCString &aAppPath, nsCStri
 static bool
 IsDevelopmentBuild()
 {
   nsCOMPtr<nsIFile> path = mozilla::Omnijar::GetPath(mozilla::Omnijar::GRE);
   // If the path doesn't exist, we're a dev build.
   return path == nullptr;
 }
 
+// This function is only used in an |#ifdef DEBUG| path.
+#ifdef DEBUG
+// Given a path to a file, return the directory which contains it.
+static nsAutoCString
+GetDirectoryPath(const char *aPath) {
+  nsCOMPtr<nsIFile> file = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
+  if (!file ||
+      NS_FAILED(file->InitWithNativePath(nsDependentCString(aPath)))) {
+    MOZ_CRASH("Failed to create or init an nsIFile");
+  }
+  nsCOMPtr<nsIFile> directoryFile;
+  if (NS_FAILED(file->GetParent(getter_AddRefs(directoryFile))) ||
+      !directoryFile) {
+    MOZ_CRASH("Failed to get parent for an nsIFile");
+  }
+  directoryFile->Normalize();
+  nsAutoCString directoryPath;
+  if (NS_FAILED(directoryFile->GetNativePath(directoryPath))) {
+    MOZ_CRASH("Failed to get path for an nsIFile");
+  }
+  return directoryPath;
+}
+#endif // DEBUG
+
 static bool
 StartMacOSContentSandbox()
 {
   int sandboxLevel = Preferences::GetInt("security.sandbox.content.level");
   if (sandboxLevel < 1) {
     return false;
   }
 
@@ -1347,16 +1371,29 @@ StartMacOSContentSandbox()
 
   if (profileDir) {
     info.hasSandboxedProfile = true;
     info.profileDir.assign(profileDirPath.get());
   } else {
     info.hasSandboxedProfile = false;
   }
 
+#ifdef DEBUG
+  // When a content process dies intentionally (|NoteIntentionalCrash|), for
+  // tests it wants to log that it did this. Allow writing to this location
+  // that the testrunner wants.
+  char *bloatLog = PR_GetEnv("XPCOM_MEM_BLOAT_LOG");
+  if (bloatLog != nullptr) {
+    // |bloatLog| points to a specific file, but we actually write to a sibling
+    // of that path.
+    nsAutoCString bloatDirectoryPath = GetDirectoryPath(bloatLog);
+    info.debugWriteDir.assign(bloatDirectoryPath.get());
+  }
+#endif // DEBUG
+
   std::string err;
   if (!mozilla::StartMacSandbox(info, err)) {
     NS_WARNING(err.c_str());
     MOZ_CRASH("sandbox_init() failed");
   }
 
   return true;
 }
--- a/security/sandbox/mac/Sandbox.h
+++ b/security/sandbox/mac/Sandbox.h
@@ -43,27 +43,29 @@ typedef struct _MacSandboxInfo {
       shouldLog(true) {}
   _MacSandboxInfo(const struct _MacSandboxInfo& other)
     : type(other.type), level(other.level),
       hasFilePrivileges(other.hasFilePrivileges),
       hasSandboxedProfile(other.hasSandboxedProfile),
       pluginInfo(other.pluginInfo),
       appPath(other.appPath), appBinaryPath(other.appBinaryPath),
       appDir(other.appDir), appTempDir(other.appTempDir),
-      profileDir(other.profileDir), shouldLog(other.shouldLog) {}
+      profileDir(other.profileDir), debugWriteDir(other.debugWriteDir),
+      shouldLog(other.shouldLog) {}
   MacSandboxType type;
   int32_t level;
   bool hasFilePrivileges;
   bool hasSandboxedProfile;
   MacSandboxPluginInfo pluginInfo;
   std::string appPath;
   std::string appBinaryPath;
   std::string appDir;
   std::string appTempDir;
   std::string profileDir;
+  std::string debugWriteDir;
   bool shouldLog;
 } MacSandboxInfo;
 
 namespace mozilla {
 
 bool StartMacSandbox(MacSandboxInfo aInfo, std::string &aErrorMessage);
 
 } // namespace mozilla
--- a/security/sandbox/mac/Sandbox.mm
+++ b/security/sandbox/mac/Sandbox.mm
@@ -173,22 +173,22 @@ bool StartMacSandbox(MacSandboxInfo aInf
       params.push_back("PROFILE_DIR");
       params.push_back(aInfo.profileDir.c_str());
       params.push_back("HOME_PATH");
       params.push_back(getenv("HOME"));
       params.push_back("HAS_SANDBOXED_PROFILE");
       params.push_back(aInfo.hasSandboxedProfile ? "TRUE" : "FALSE");
       params.push_back("HAS_FILE_PRIVILEGES");
       params.push_back(aInfo.hasFilePrivileges ? "TRUE" : "FALSE");
-      params.push_back("DEBUG_BUILD");
 #ifdef DEBUG
-      params.push_back("TRUE");
-#else
-      params.push_back("FALSE");
-#endif
+      if (!aInfo.debugWriteDir.empty()) {
+        params.push_back("DEBUG_WRITE_DIR");
+        params.push_back(aInfo.debugWriteDir.c_str());
+      }
+#endif // DEBUG
     } else {
       fprintf(stderr,
         "Content sandbox disabled due to sandbox level setting\n");
       return false;
     }
   }
   else {
     char *msg = NULL;
--- a/security/sandbox/mac/SandboxPolicies.h
+++ b/security/sandbox/mac/SandboxPolicies.h
@@ -44,30 +44,30 @@ static const char pluginSandboxRules[] =
 
 static const char widevinePluginSandboxRulesAddend[] = R"(
   (allow mach-lookup (global-name "com.apple.windowserver.active"))
 )";
 
 static const char contentSandboxRules[] = R"(
   (version 1)
 
-      (define should-log (param "SHOULD_LOG"))
+  (define should-log (param "SHOULD_LOG"))
   (define sandbox-level-1 (param "SANDBOX_LEVEL_1"))
   (define sandbox-level-2 (param "SANDBOX_LEVEL_2"))
   (define sandbox-level-3 (param "SANDBOX_LEVEL_3"))
   (define macosMinorVersion-9 (param "MAC_OS_MINOR_9"))
   (define appPath (param "APP_PATH"))
   (define appBinaryPath (param "APP_BINARY_PATH"))
   (define appDir (param "APP_DIR"))
   (define appTempDir (param "APP_TEMP_DIR"))
   (define hasProfileDir (param "HAS_SANDBOXED_PROFILE"))
   (define profileDir (param "PROFILE_DIR"))
   (define home-path (param "HOME_PATH"))
   (define hasFilePrivileges (param "HAS_FILE_PRIVILEGES"))
-  (define isDebugBuild (param "DEBUG_BUILD"))
+  (define debugWriteDir (param "DEBUG_WRITE_DIR"))
 
   ; Allow read access to standard system paths.
   (allow file-read*
     (require-all (file-mode #o0004)
       (require-any (subpath "/Library/Filesystems/NetFSPlugins")
         (subpath "/System")
         (subpath "/usr/lib")
         (subpath "/usr/share"))))
@@ -219,18 +219,18 @@ static const char contentSandboxRules[] 
 
     (allow file-read-metadata (home-subpath "/Library"))
 
     (allow file-read-metadata
       (literal "/private/var")
       (subpath "/private/var/folders"))
 
   ; bug 1303987
-    (if (string=? isDebugBuild "TRUE")
-        (allow file-write* (subpath "/private/var")))
+    (if (string? debugWriteDir)
+      (allow file-write* (subpath debugWriteDir)))
 
   ; bug 1324610
     (allow network-outbound (literal "/private/var/run/cupsd"))
 
     (allow-shared-list "org.mozilla.plugincontainer")
 
   ; the following rule should be removed when microphone access
   ; is brokered through the content process
@@ -317,18 +317,17 @@ static const char contentSandboxRules[] 
         (iokit-user-client-class "AppleGraphicsPolicyClient"))
 
   ; bug 1153809
     (allow iokit-open
         (iokit-user-client-class "NVDVDContextTesla")
         (iokit-user-client-class "Gen6DVDContext"))
 
   ; bug 1237847
-    (allow file-read*
+    (allow file-read* file-write*
         (subpath appTempDir))
-    (allow file-write*
-        (subpath appTempDir))
+
   )
 )";
 
 }
 
 #endif // mozilla_SandboxPolicies_h