Bug 1386832 - Part 1 - Move non-sandbox-specific routines out of SandboxSettings. r=jimm draft
authorHaik Aftandilian <haftandilian@mozilla.com>
Wed, 09 Aug 2017 16:09:55 -0700
changeset 643623 3529a18ea802699ff968b798a7c560613469809b
parent 643622 2ce9ac9f2f79328fe464566ef08a88c5cb69baeb
child 643624 64d1008a0513938edc111d12cb9fb28d2048ac82
push id73155
push userhaftandilian@mozilla.com
push dateWed, 09 Aug 2017 23:42:18 +0000
reviewersjimm
bugs1386832
milestone57.0a1
Bug 1386832 - Part 1 - Move non-sandbox-specific routines out of SandboxSettings. r=jimm Moves IsDevelopmentBuild(), GetRepoDir(), and GetObjectDir() out of SandboxSettings because they also need to be used by ExtensionProtocolHandler to do security checks on developer builds as a result of how developer builds rely on symlinks to the repo dir from system extension directories. Remove the Linux-implementation of GetRepoDir() and GetObjectDir() because the Linux content sandbox implementation and the ExtensionProtocolHandler checks don't need them. MozReview-Commit-ID: KwBFUnh6Cml
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
security/sandbox/common/SandboxSettings.cpp
security/sandbox/common/SandboxSettings.h
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -68,16 +68,20 @@
 #include "nsBaseDragService.h"
 #include "mozilla/media/MediaChild.h"
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/WebBrowserPersistDocumentChild.h"
 #include "imgLoader.h"
 #include "GMPServiceChild.h"
 #include "NullPrincipal.h"
 
+#if !defined(XP_WIN)
+#include "mozilla/Omnijar.h"
+#endif
+
 #ifdef MOZ_GECKO_PROFILER
 #include "ChildProfilerController.h"
 #endif
 
 #if defined(MOZ_CONTENT_SANDBOX)
 #include "mozilla/SandboxSettings.h"
 #if defined(XP_WIN)
 #define TARGET_SANDBOX_EXPORTS
@@ -167,16 +171,24 @@
 
 #ifdef XP_WIN
 #include <process.h>
 #define getpid _getpid
 #include "mozilla/widget/AudioSession.h"
 #include "mozilla/audio/AudioNotificationReceiver.h"
 #endif
 
+#if defined(XP_MACOSX)
+#include <CoreServices/CoreServices.h>
+// Info.plist key associated with the developer repo path
+#define MAC_DEV_REPO_KEY "MozillaDeveloperRepoPath"
+// Info.plist key associated with the developer repo object directory
+#define MAC_DEV_OBJ_KEY "MozillaDeveloperObjPath"
+#endif /* XP_MACOSX */
+
 #ifdef MOZ_X11
 #include "mozilla/X11Util.h"
 #endif
 
 #ifdef ACCESSIBILITY
 #include "nsAccessibilityService.h"
 #ifdef XP_WIN
 #include "mozilla/a11y/AccessibleWrap.h"
@@ -3544,9 +3556,130 @@ ContentChild::GetSpecificMessageEventTar
       || aMsg.type() == PJavaScript::Msg_DropObject__ID) {
     return do_AddRef(SystemGroup::EventTargetFor(TaskCategory::Other));
   }
 
   return nullptr;
 }
 
 } // namespace dom
+
+#if !defined(XP_WIN)
+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;
+}
+#endif /* !XP_WIN */
+
+#if defined(XP_MACOSX)
+/*
+ * Helper function to read a string value for a given key from the .app's
+ * Info.plist.
+ */
+static nsresult
+GetStringValueFromBundlePlist(const nsAString& aKey, nsAutoCString& aValue)
+{
+  CFBundleRef mainBundle = CFBundleGetMainBundle();
+  if (mainBundle == nullptr) {
+    return NS_ERROR_FAILURE;
+  }
+
+  // Read this app's bundle Info.plist as a dictionary
+  CFDictionaryRef bundleInfoDict = CFBundleGetInfoDictionary(mainBundle);
+  if (bundleInfoDict == nullptr) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsAutoCString keyAutoCString = NS_ConvertUTF16toUTF8(aKey);
+  CFStringRef key = CFStringCreateWithCString(kCFAllocatorDefault,
+                                              keyAutoCString.get(),
+                                              kCFStringEncodingUTF8);
+  if (key == nullptr) {
+    return NS_ERROR_FAILURE;
+  }
+
+  CFStringRef value = (CFStringRef)CFDictionaryGetValue(bundleInfoDict, key);
+  CFRelease(key);
+  if (value == nullptr) {
+    return NS_ERROR_FAILURE;
+  }
+
+  CFIndex valueLength = CFStringGetLength(value);
+  if (valueLength == 0) {
+    return NS_ERROR_FAILURE;
+  }
+
+  const char* valueCString = CFStringGetCStringPtr(value,
+                                                   kCFStringEncodingUTF8);
+  if (valueCString) {
+    aValue.Assign(valueCString);
+    return NS_OK;
+  }
+
+  CFIndex maxLength =
+    CFStringGetMaximumSizeForEncoding(valueLength, kCFStringEncodingUTF8) + 1;
+  char* valueBuffer = static_cast<char*>(moz_xmalloc(maxLength));
+  if (!valueBuffer) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  if (!CFStringGetCString(value, valueBuffer, maxLength,
+                          kCFStringEncodingUTF8)) {
+    free(valueBuffer);
+    return NS_ERROR_FAILURE;
+  }
+
+  aValue.Assign(valueBuffer);
+  free(valueBuffer);
+  return NS_OK;
+}
+
+/*
+ * Helper function for reading a path string from the .app's Info.plist
+ * and returning a directory object for that path with symlinks resolved.
+ */
+static nsresult
+GetDirFromBundlePlist(const nsAString& aKey, nsIFile **aDir)
+{
+  nsresult rv;
+
+  nsAutoCString dirPath;
+  rv = GetStringValueFromBundlePlist(aKey, dirPath);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIFile> dir;
+  rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(dirPath),
+                       false,
+                       getter_AddRefs(dir));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = dir->Normalize();
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  bool isDirectory = false;
+  rv = dir->IsDirectory(&isDirectory);
+  NS_ENSURE_SUCCESS(rv, rv);
+  if (!isDirectory) {
+    return NS_ERROR_FILE_NOT_DIRECTORY;
+  }
+
+  dir.swap(*aDir);
+  return NS_OK;
+}
+
+nsresult
+GetRepoDir(nsIFile **aRepoDir)
+{
+  MOZ_ASSERT(IsDevelopmentBuild());
+  return GetDirFromBundlePlist(NS_LITERAL_STRING(MAC_DEV_REPO_KEY), aRepoDir);
+}
+
+nsresult
+GetObjDir(nsIFile **aObjDir)
+{
+  MOZ_ASSERT(IsDevelopmentBuild());
+  return GetDirFromBundlePlist(NS_LITERAL_STRING(MAC_DEV_OBJ_KEY), aObjDir);
+}
+#endif /* XP_MACOSX */
+
 } // namespace mozilla
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -35,16 +35,33 @@ class nsIURIClassifierCallback;
 struct LookAndFeelInt;
 
 namespace mozilla {
 class RemoteSpellcheckEngineChild;
 class ChildProfilerController;
 
 using mozilla::loader::PScriptCacheChild;
 
+#if !defined(XP_WIN)
+// Returns whether or not the currently running build is an unpackaged
+// developer build. This check is implemented by looking for omni.ja in the
+// the obj/dist dir. We use this routine to detect when the build dir will
+// use symlinks to the repo and object dir. On Windows, dev builds don't
+// use symlinks.
+bool IsDevelopmentBuild();
+#endif /* !XP_WIN */
+
+#if defined(XP_MACOSX)
+// Return the repo directory and the repo object directory respectively. These
+// should only be used on Mac developer builds to determine the path to the
+// repo or object directory.
+nsresult GetRepoDir(nsIFile **aRepoDir);
+nsresult GetObjDir(nsIFile **aObjDir);
+#endif /* XP_MACOSX */
+
 namespace ipc {
 class OptionalURIParams;
 class URIParams;
 }// namespace ipc
 
 namespace dom {
 
 class AlertObserver;
--- a/security/sandbox/common/SandboxSettings.cpp
+++ b/security/sandbox/common/SandboxSettings.cpp
@@ -1,195 +1,21 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozISandboxSettings.h"
 
-#include "mozilla/Omnijar.h"
 #include "mozilla/ModuleUtils.h"
 #include "mozilla/Preferences.h"
 
-#include "nsDirectoryServiceDefs.h"
-
-#if defined(XP_MACOSX)
-#include <CoreServices/CoreServices.h>
-// Info.plist key associated with the developer repo path
-#define MAC_DEV_REPO_KEY "MozillaDeveloperRepoPath"
-// Info.plist key associated with the developer repo object directory
-#define MAC_DEV_OBJ_KEY "MozillaDeveloperObjPath"
-#else
-#include "prenv.h"
-#endif /* XP_MACOSX */
-
 namespace mozilla {
 
-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;
-}
-
-#if defined(XP_MACOSX)
-/*
- * Helper function to read a string value for a given key from the .app's
- * Info.plist.
- */
-static nsresult
-GetStringValueFromBundlePlist(const nsAString& aKey, nsAutoCString& aValue)
-{
-  CFBundleRef mainBundle = CFBundleGetMainBundle();
-  if (mainBundle == nullptr) {
-    return NS_ERROR_FAILURE;
-  }
-
-  // Read this app's bundle Info.plist as a dictionary
-  CFDictionaryRef bundleInfoDict = CFBundleGetInfoDictionary(mainBundle);
-  if (bundleInfoDict == nullptr) {
-    return NS_ERROR_FAILURE;
-  }
-
-  nsAutoCString keyAutoCString = NS_ConvertUTF16toUTF8(aKey);
-  CFStringRef key = CFStringCreateWithCString(kCFAllocatorDefault,
-                                              keyAutoCString.get(),
-                                              kCFStringEncodingUTF8);
-  if (key == nullptr) {
-    return NS_ERROR_FAILURE;
-  }
-
-  CFStringRef value = (CFStringRef)CFDictionaryGetValue(bundleInfoDict, key);
-  CFRelease(key);
-  if (value == nullptr) {
-    return NS_ERROR_FAILURE;
-  }
-
-  CFIndex valueLength = CFStringGetLength(value);
-  if (valueLength == 0) {
-    return NS_ERROR_FAILURE;
-  }
-
-  const char* valueCString = CFStringGetCStringPtr(value,
-                                                   kCFStringEncodingUTF8);
-  if (valueCString) {
-    aValue.Assign(valueCString);
-    return NS_OK;
-  }
-
-  CFIndex maxLength =
-    CFStringGetMaximumSizeForEncoding(valueLength, kCFStringEncodingUTF8) + 1;
-  char* valueBuffer = static_cast<char*>(moz_xmalloc(maxLength));
-  if (!valueBuffer) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
-  if (!CFStringGetCString(value, valueBuffer, maxLength,
-                          kCFStringEncodingUTF8)) {
-    free(valueBuffer);
-    return NS_ERROR_FAILURE;
-  }
-
-  aValue.Assign(valueBuffer);
-  free(valueBuffer);
-  return NS_OK;
-}
-
-/*
- * Helper function for reading a path string from the .app's Info.plist
- * and returning a directory object for that path with symlinks resolved.
- */
-static nsresult
-GetDirFromBundlePlist(const nsAString& aKey, nsIFile **aDir)
-{
-  nsresult rv;
-
-  nsAutoCString dirPath;
-  rv = GetStringValueFromBundlePlist(aKey, dirPath);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIFile> dir;
-  rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(dirPath),
-                       false,
-                       getter_AddRefs(dir));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = dir->Normalize();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  bool isDirectory = false;
-  rv = dir->IsDirectory(&isDirectory);
-  NS_ENSURE_SUCCESS(rv, rv);
-  if (!isDirectory) {
-    return NS_ERROR_FILE_NOT_DIRECTORY;
-  }
-
-  dir.swap(*aDir);
-  return NS_OK;
-}
-
-#else /* !XP_MACOSX */
-
-/*
- * Helper function for getting a directory object for a given env variable
- */
-static nsresult
-GetDirFromEnv(const char* aEnvVar, nsIFile **aDir)
-{
-  nsresult rv;
-
-  nsCOMPtr<nsIFile> dir;
-  const char *dir_path = PR_GetEnv(aEnvVar);
-  if (!dir_path) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(dir_path),
-                       false,
-                       getter_AddRefs(dir));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = dir->Normalize();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  bool isDirectory = false;
-  rv = dir->IsDirectory(&isDirectory);
-  NS_ENSURE_SUCCESS(rv, rv);
-  if (!isDirectory) {
-    return NS_ERROR_FILE_NOT_DIRECTORY;
-  }
-
-  dir.swap(*aDir);
-  return NS_OK;
-}
-#endif /* XP_MACOSX */
-
-nsresult
-GetRepoDir(nsIFile **aRepoDir)
-{
-  MOZ_ASSERT(IsDevelopmentBuild());
-#if defined(XP_MACOSX)
-  return GetDirFromBundlePlist(NS_LITERAL_STRING(MAC_DEV_REPO_KEY), aRepoDir);
-#else
-  return GetDirFromEnv("MOZ_DEVELOPER_REPO_DIR", aRepoDir);
-#endif /* XP_MACOSX */
-}
-
-nsresult
-GetObjDir(nsIFile **aObjDir)
-{
-  MOZ_ASSERT(IsDevelopmentBuild());
-#if defined(XP_MACOSX)
-  return GetDirFromBundlePlist(NS_LITERAL_STRING(MAC_DEV_OBJ_KEY), aObjDir);
-#else
-  return GetDirFromEnv("MOZ_DEVELOPER_OBJ_DIR", aObjDir);
-#endif /* XP_MACOSX */
-}
-
 int GetEffectiveContentSandboxLevel() {
   int level = Preferences::GetInt("security.sandbox.content.level");
 // On Windows and macOS, enforce a minimum content sandbox level of 1 (except on
 // Nightly, where it can be set to 0).
 #if !defined(NIGHTLY_BUILD) && (defined(XP_WIN) || defined(XP_MACOSX))
   if (level < 1) {
     level = 1;
   }
--- a/security/sandbox/common/SandboxSettings.h
+++ b/security/sandbox/common/SandboxSettings.h
@@ -8,21 +8,10 @@
 
 namespace mozilla {
 
 // Return the current sandbox level. This is the
 // "security.sandbox.content.level" preference, but rounded up to the current
 // minimum allowed level.
 int GetEffectiveContentSandboxLevel();
 
-// Returns whether or not the currently running build is a development build -
-// where development build means "the files in the .app are symlinks to the src
-// directory". This check is implemented by looking for omni.ja in
-// .app/Contents/Resources/.
-bool IsDevelopmentBuild();
-
-// Return the repo directory and the repo object directory respectively. These
-// should only be used on developer builds to determine the path to the repo
-// or object directory.
-nsresult GetRepoDir(nsIFile **aRepoDir);
-nsresult GetObjDir(nsIFile **aObjDir);
 }
 #endif // mozilla_SandboxPolicies_h