Bug 1380132 - Part 3 - Use env variable MOZ_DEVELOPER_OBJ_DIR to whitelist object dir in content sandbox. r?Alex_Gaynor draft
authorHaik Aftandilian <haftandilian@mozilla.com>
Fri, 14 Jul 2017 16:32:53 -0700
changeset 609176 8aed9762c421bfab7ec12288daad0aebba86c346
parent 609175 7d621a1dc7ced33a2c00e906970401e152a70189
child 637531 a3bcfd4b6631413c9272d21361b8e5a636b7e0ab
push id68534
push userhaftandilian@mozilla.com
push dateFri, 14 Jul 2017 23:38:36 +0000
reviewersAlex_Gaynor
bugs1380132
milestone56.0a1
Bug 1380132 - Part 3 - Use env variable MOZ_DEVELOPER_OBJ_DIR to whitelist object dir in content sandbox. r?Alex_Gaynor On developer builds, use $MOZ_DEVELOPER_OBJ_DIR to whitelist the object dir in the content sandbox so that symlinks to the object dir from .app/ files can be loaded. MozReview-Commit-ID: J4YdpxgbD8i
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
@@ -1453,16 +1453,33 @@ GetDirectoryPath(const char *aPath) {
   nsAutoCString directoryPath;
   if (NS_FAILED(directoryFile->GetNativePath(directoryPath))) {
     MOZ_CRASH("Failed to get path for an nsIFile");
   }
   return directoryPath;
 }
 #endif // DEBUG
 
+static nsresult
+NormalizePath(const char* aPath, nsCString& aOutPath)
+{
+  nsresult rv;
+
+  nsCOMPtr<nsIFile> file;
+  rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(aPath), true, getter_AddRefs(file));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = file->Normalize();
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = file->GetNativePath(aOutPath);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return NS_OK;
+}
+
 static bool
 StartMacOSContentSandbox()
 {
   int sandboxLevel = GetEffectiveContentSandboxLevel();
   if (sandboxLevel < 1) {
     return false;
   }
 
@@ -1498,21 +1515,23 @@ StartMacOSContentSandbox()
     rv = profileDir->GetNativePath(profileDirPath);
     if (NS_FAILED(rv) || profileDirPath.IsEmpty()) {
       MOZ_CRASH("Failed to get profile path");
     }
   }
 
   bool isFileProcess = cc->GetRemoteType().EqualsLiteral(FILE_REMOTE_TYPE);
   char *developer_repo_dir = nullptr;
+  char *developer_obj_dir = nullptr;
   if (mozilla::IsDevelopmentBuild()) {
     // If this is a developer build the resources in the .app are symlinks to
     // outside of the .app. Therefore in non-release builds we allow reads from
     // the whole repository. MOZ_DEVELOPER_REPO_DIR is set by mach run.
     developer_repo_dir = PR_GetEnv("MOZ_DEVELOPER_REPO_DIR");
+    developer_obj_dir = PR_GetEnv("MOZ_DEVELOPER_OBJ_DIR");
   }
 
   MacSandboxInfo info;
   info.type = MacSandboxType_Content;
   info.level = sandboxLevel;
   info.hasFilePrivileges = isFileProcess;
   info.shouldLog = Preferences::GetBool("security.sandbox.logging.enabled") ||
                    PR_GetEnv("MOZ_SANDBOX_LOGGING");
@@ -1529,18 +1548,33 @@ StartMacOSContentSandbox()
   if (!testingReadPath1.IsEmpty()) {
     info.testingReadPath1.assign(testingReadPath1.get());
   }
   nsAdoptingCString testingReadPath2 =
     Preferences::GetCString("security.sandbox.content.mac.testing_read_path2");
   if (!testingReadPath2.IsEmpty()) {
     info.testingReadPath2.assign(testingReadPath2.get());
   }
+
   if (developer_repo_dir) {
-    info.testingReadPath3.assign(developer_repo_dir);
+    nsCString repoDirPath;
+    rv = NormalizePath(developer_repo_dir, repoDirPath);
+    if (NS_FAILED(rv)) {
+      MOZ_CRASH("Failed to normalize repo path");
+    }
+    info.testingReadPath3.assign(repoDirPath.get());
+  }
+
+  if (developer_obj_dir) {
+    nsCString objDirPath;
+    rv = NormalizePath(developer_obj_dir, objDirPath);
+    if (NS_FAILED(rv)) {
+      MOZ_CRASH("Failed to normalize obj dir path");
+    }
+    info.testingReadPath4.assign(objDirPath.get());
   }
 
   if (profileDir) {
     info.hasSandboxedProfile = true;
     info.profileDir.assign(profileDirPath.get());
   } else {
     info.hasSandboxedProfile = false;
   }
--- a/security/sandbox/mac/Sandbox.h
+++ b/security/sandbox/mac/Sandbox.h
@@ -46,32 +46,34 @@ typedef struct _MacSandboxInfo {
       hasFilePrivileges(other.hasFilePrivileges),
       hasSandboxedProfile(other.hasSandboxedProfile),
       pluginInfo(other.pluginInfo),
       appPath(other.appPath), appBinaryPath(other.appBinaryPath),
       appDir(other.appDir), appTempDir(other.appTempDir),
       profileDir(other.profileDir), debugWriteDir(other.debugWriteDir),
       testingReadPath1(other.testingReadPath1),
       testingReadPath2(other.testingReadPath2),
-      testingReadPath3(other.testingReadPath3), shouldLog(other.shouldLog) {}
+      testingReadPath3(other.testingReadPath3),
+      testingReadPath4(other.testingReadPath4), 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;
 
   std::string testingReadPath1;
   std::string testingReadPath2;
   std::string testingReadPath3;
+  std::string testingReadPath4;
 
   bool shouldLog;
 } MacSandboxInfo;
 
 namespace mozilla {
 
 bool StartMacSandbox(MacSandboxInfo aInfo, std::string &aErrorMessage);
 
--- a/security/sandbox/mac/Sandbox.mm
+++ b/security/sandbox/mac/Sandbox.mm
@@ -187,16 +187,20 @@ bool StartMacSandbox(MacSandboxInfo aInf
       if (!aInfo.testingReadPath2.empty()) {
         params.push_back("TESTING_READ_PATH2");
         params.push_back(aInfo.testingReadPath2.c_str());
       }
       if (!aInfo.testingReadPath3.empty()) {
         params.push_back("TESTING_READ_PATH3");
         params.push_back(aInfo.testingReadPath3.c_str());
       }
+      if (!aInfo.testingReadPath4.empty()) {
+        params.push_back("TESTING_READ_PATH4");
+        params.push_back(aInfo.testingReadPath4.c_str());
+      }
 #ifdef DEBUG
       if (!aInfo.debugWriteDir.empty()) {
         params.push_back("DEBUG_WRITE_DIR");
         params.push_back(aInfo.debugWriteDir.c_str());
       }
 #endif // DEBUG
     } else {
       fprintf(stderr,
--- a/security/sandbox/mac/SandboxPolicies.h
+++ b/security/sandbox/mac/SandboxPolicies.h
@@ -63,16 +63,17 @@ static const char contentSandboxRules[] 
   (define hasProfileDir (param "HAS_SANDBOXED_PROFILE"))
   (define profileDir (param "PROFILE_DIR"))
   (define home-path (param "HOME_PATH"))
   (define hasFilePrivileges (param "HAS_FILE_PRIVILEGES"))
   (define debugWriteDir (param "DEBUG_WRITE_DIR"))
   (define testingReadPath1 (param "TESTING_READ_PATH1"))
   (define testingReadPath2 (param "TESTING_READ_PATH2"))
   (define testingReadPath3 (param "TESTING_READ_PATH3"))
+  (define testingReadPath4 (param "TESTING_READ_PATH4"))
 
   (if (string=? should-log "TRUE")
     (deny default)
     (deny default (with no-log)))
   (debug deny)
 
   ; Allow read access to standard system paths.
   (allow file-read*
@@ -261,16 +262,18 @@ static const char contentSandboxRules[] 
       (literal appBinaryPath))
 
   (when testingReadPath1
     (allow file-read* (subpath testingReadPath1)))
   (when testingReadPath2
     (allow file-read* (subpath testingReadPath2)))
   (when testingReadPath3
     (allow file-read* (subpath testingReadPath3)))
+  (when testingReadPath4
+    (allow file-read* (subpath testingReadPath4)))
 
   (allow file-read-metadata (home-subpath "/Library"))
 
   (allow file-read-metadata
     (literal "/private/var")
     (subpath "/private/var/folders"))
 
 ; bug 1303987