Bug 1365257 - Further consolidate the configuration of the content sandbox; r=gcp
☠☠ backed out by 1be6d94e8015 ☠ ☠
authorAlex Gaynor <agaynor@mozilla.com>
Thu, 01 Jun 2017 10:38:22 -0400
changeset 444552 00edc1ac58f9e9eb7c2773013b95a6a87d1fcc3e
parent 444551 efbc0ed871b56804ba361b8d236e448103b7f529
child 444553 c1cefe2b0443d602d20ae03ab26531bc86e20e31
push id1618
push userCallek@gmail.com
push dateThu, 11 Jan 2018 17:45:48 +0000
treeherdermozilla-release@882ca853e05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgcp
bugs1365257
milestone58.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 1365257 - Further consolidate the configuration of the content sandbox; r=gcp This patch moves handling of the "MOZ_DISABLE_CONTENT_SANDBOX" environment variable into GetEffectiveContentSandboxLevel. It also introduces IsContentSandboxEnabled and ports many users of GetEffectiveContentSandboxLevel to use it. MozReview-Commit-ID: 4CsOf89vlRB
dom/ipc/ContentParent.cpp
dom/ipc/ContentProcess.cpp
ipc/glue/GeckoChildProcessHost.cpp
security/sandbox/common/SandboxSettings.cpp
security/sandbox/common/SandboxSettings.h
security/sandbox/linux/Sandbox.h
security/sandbox/linux/SandboxInfo.cpp
security/sandbox/linux/SandboxInfo.h
security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp
toolkit/xre/nsXREDirProvider.cpp
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -2381,18 +2381,17 @@ ContentParent::InitInternal(ProcessPrior
 #ifdef MOZ_CONTENT_SANDBOX
   bool shouldSandbox = true;
   MaybeFileDesc brokerFd = void_t();
   // XXX: Checking the pref here makes it possible to enable/disable sandboxing
   // during an active session. Currently the pref is only used for testing
   // purpose. If the decision is made to permanently rely on the pref, this
   // should be changed so that it is required to restart firefox for the change
   // of value to take effect.
-  shouldSandbox = (GetEffectiveContentSandboxLevel() > 0) &&
-    !PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX");
+  shouldSandbox = IsContentSandboxEnabled();
 
 #ifdef XP_LINUX
   if (shouldSandbox) {
     MOZ_ASSERT(!mSandboxBroker);
     bool isFileProcess = mRemoteType.EqualsLiteral(FILE_REMOTE_TYPE);
     UniquePtr<SandboxBroker::Policy> policy =
       sSandboxBrokerPolicyFactory->GetContentPolicy(Pid(), isFileProcess);
     if (policy) {
--- a/dom/ipc/ContentProcess.cpp
+++ b/dom/ipc/ContentProcess.cpp
@@ -23,24 +23,16 @@
 #endif
 
 using mozilla::ipc::IOThreadChild;
 
 namespace mozilla {
 namespace dom {
 
 #if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
-static bool
-IsSandboxTempDirRequired()
-{
-  // On Windows, a sandbox-writable temp directory is only used
-  // when sandbox pref level >= 1.
-  return GetEffectiveContentSandboxLevel() >= 1;
-}
-
 static void
 SetTmpEnvironmentVariable(nsIFile* aValue)
 {
   // Save the TMP environment variable so that is is picked up by GetTempPath().
   // Note that we specifically write to the TMP variable, as that is the first
   // variable that is checked by GetTempPath() to determine its output.
   nsAutoString fullTmpPath;
   nsresult rv = aValue->GetPath(fullTmpPath);
@@ -50,23 +42,16 @@ SetTmpEnvironmentVariable(nsIFile* aValu
   Unused << NS_WARN_IF(!SetEnvironmentVariableW(L"TMP", fullTmpPath.get()));
   // We also set TEMP in case there is naughty third-party code that is
   // referencing the environment variable directly.
   Unused << NS_WARN_IF(!SetEnvironmentVariableW(L"TEMP", fullTmpPath.get()));
 }
 #endif
 
 #if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
-static bool
-IsSandboxTempDirRequired()
-{
-  // On OSX, use the sandbox-writable temp when the pref level >= 1.
-  return (GetEffectiveContentSandboxLevel() >= 1);
-}
-
 static void
 SetTmpEnvironmentVariable(nsIFile* aValue)
 {
   nsAutoCString fullTmpPath;
   nsresult rv = aValue->GetNativePath(fullTmpPath);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
@@ -76,17 +61,19 @@ SetTmpEnvironmentVariable(nsIFile* aValu
 
 #if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
 static void
 SetUpSandboxEnvironment()
 {
   MOZ_ASSERT(nsDirectoryService::gService,
     "SetUpSandboxEnvironment relies on nsDirectoryService being initialized");
 
-  if (!IsSandboxTempDirRequired()) {
+  // On macOS and Windows, a sandbox-writable temp directory is used whenever
+  // the sandbox is enabled.
+  if (!IsContentSandboxEnabled()) {
     return;
   }
 
   nsCOMPtr<nsIFile> sandboxedContentTemp;
   nsresult rv =
     nsDirectoryService::gService->Get(NS_APP_CONTENT_PROCESS_TEMP_DIR,
                                       NS_GET_IID(nsIFile),
                                       getter_AddRefs(sandboxedContentTemp));
--- a/ipc/glue/GeckoChildProcessHost.cpp
+++ b/ipc/glue/GeckoChildProcessHost.cpp
@@ -945,18 +945,17 @@ GeckoChildProcessHost::PerformAsyncLaunc
   bool shouldSandboxCurrentProcess = false;
 
   // XXX: Bug 1124167: We should get rid of the process specific logic for
   // sandboxing in this class at some point. Unfortunately it will take a bit
   // of reorganizing so I don't think this patch is the right time.
   switch (mProcessType) {
     case GeckoProcessType_Content:
 #  if defined(MOZ_CONTENT_SANDBOX)
-      if (mSandboxLevel > 0 &&
-          !PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX")) {
+      if (IsContentSandboxEnabled()) {
         // For now we treat every failure as fatal in SetSecurityLevelForContentProcess
         // and just crash there right away. Should this change in the future then we
         // should also handle the error here.
         mSandboxBroker.SetSecurityLevelForContentProcess(mSandboxLevel,
                                                          mIsFileContent);
         shouldSandboxCurrentProcess = true;
       }
 #  endif // defined(MOZ_CONTENT_SANDBOX)
--- a/security/sandbox/common/SandboxSettings.cpp
+++ b/security/sandbox/common/SandboxSettings.cpp
@@ -4,30 +4,39 @@
  * 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/ModuleUtils.h"
 #include "mozilla/Preferences.h"
 
+#include "prenv.h"
+
 namespace mozilla {
 
 int GetEffectiveContentSandboxLevel() {
+  if (PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX")) {
+    return 0;
+  }
   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;
   }
 #endif
   return level;
 }
 
+bool IsContentSandboxEnabled() {
+  return GetEffectiveContentSandboxLevel() > 0;
+}
+
 class SandboxSettings final : public mozISandboxSettings
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_MOZISANDBOXSETTINGS
 
   SandboxSettings() { }
 
--- a/security/sandbox/common/SandboxSettings.h
+++ b/security/sandbox/common/SandboxSettings.h
@@ -5,13 +5,17 @@
 
 #ifndef mozilla_SandboxSettings_h
 #define mozilla_SandboxSettings_h
 
 namespace mozilla {
 
 // Return the current sandbox level. This is the
 // "security.sandbox.content.level" preference, but rounded up to the current
-// minimum allowed level.
+// minimum allowed level. Returns 0 (disabled) if the env var
+// MOZ_DISABLE_CONTENT_SANDBOX is set.
 int GetEffectiveContentSandboxLevel();
 
+// Checks whether the effective content sandbox level is > 0.
+bool IsContentSandboxEnabled();
+
 }
 #endif // mozilla_SandboxPolicies_h
--- a/security/sandbox/linux/Sandbox.h
+++ b/security/sandbox/linux/Sandbox.h
@@ -17,17 +17,17 @@
 
 namespace mozilla {
 
 // This must be called early, while the process is still single-threaded.
 MOZ_EXPORT void SandboxEarlyInit(GeckoProcessType aType);
 
 #ifdef MOZ_CONTENT_SANDBOX
 // Call only if SandboxInfo::CanSandboxContent() returns true.
-// (No-op if MOZ_DISABLE_CONTENT_SANDBOX is set.)
+// (No-op if the sandbox is disabled.)
 // aBrokerFd is the filesystem broker client file descriptor,
 // or -1 to allow direct filesystem access.
 // isFileProcess determines whether we allow system wide file reads.
 MOZ_EXPORT bool SetContentProcessSandbox(int aBrokerFd,
                                          bool aFileProcess,
                                          std::vector<int>& aSyscallWhitelist);
 #endif
 
--- a/security/sandbox/linux/SandboxInfo.cpp
+++ b/security/sandbox/linux/SandboxInfo.cpp
@@ -14,16 +14,17 @@
 #include <sys/stat.h>
 #include <sys/syscall.h>
 #include <sys/wait.h>
 #include <unistd.h>
 
 #include "base/posix/eintr_wrapper.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/ArrayUtils.h"
+#include "mozilla/SandboxSettings.h"
 #include "sandbox/linux/system_headers/linux_seccomp.h"
 #include "sandbox/linux/system_headers/linux_syscalls.h"
 
 #ifdef MOZ_VALGRIND
 #include <valgrind/valgrind.h>
 #endif
 
 
@@ -221,16 +222,19 @@ SandboxInfo::SandboxInfo() {
       flags |= kHasPrivilegedUserNamespaces;
       if (CanCreateUserNamespace()) {
         flags |= kHasUserNamespaces;
       }
     }
   }
 
 #ifdef MOZ_CONTENT_SANDBOX
+  // We can't use mozilla::IsContentSandboxEnabled() here because a)
+  // libmozsandbox can't depend on libxul, and b) this is called in a static
+  // initializer before the prefences service is ready.
   if (!getenv("MOZ_DISABLE_CONTENT_SANDBOX")) {
     flags |= kEnabledForContent;
   }
   if (getenv("MOZ_PERMISSIVE_CONTENT_SANDBOX")) {
     flags |= kPermissive;
   }
 #endif
 #ifdef MOZ_GMP_SANDBOX
--- a/security/sandbox/linux/SandboxInfo.h
+++ b/security/sandbox/linux/SandboxInfo.h
@@ -20,17 +20,18 @@ public:
   SandboxInfo(const SandboxInfo& aOther) : mFlags(aOther.mFlags) { }
 
   // Flags are checked at initializer time; this returns them.
   static const SandboxInfo& Get() { return sSingleton; }
 
   enum Flags {
     // System call filtering; kernel config option CONFIG_SECCOMP_FILTER.
     kHasSeccompBPF     = 1 << 0,
-    // Config flag MOZ_CONTENT_SANDBOX; env var MOZ_DISABLE_CONTENT_SANDBOX.
+    // Config flag MOZ_CONTENT_SANDBOX; runtime
+    // mozilla::IsContentSandboxEnabled().
     kEnabledForContent = 1 << 1,
     // Config flag MOZ_GMP_SANDBOX; env var MOZ_DISABLE_GMP_SANDBOX.
     kEnabledForMedia   = 1 << 2,
     // Env var MOZ_SANDBOX_LOGGING.
     kVerbose           = 1 << 3,
     // Kernel can atomically set system call filtering on entire thread group.
     kHasSeccompTSync   = 1 << 4,
     // Can this process create user namespaces? (Man page user_namespaces(7).)
--- a/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp
+++ b/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp
@@ -398,17 +398,17 @@ SandboxBrokerPolicyFactory::GetContentPo
 {
   // Policy entries that vary per-process (currently the only reason
   // that can happen is because they contain the pid) are added here,
   // as well as entries that depend on preferences or paths not available
   // in early startup.
 
   MOZ_ASSERT(NS_IsMainThread());
   // File broker usage is controlled through a pref.
-  if (GetEffectiveContentSandboxLevel() <= 1) {
+  if (!IsContentSandboxEnabled()) {
     return nullptr;
   }
 
   MOZ_ASSERT(mCommonContentPolicy);
   UniquePtr<SandboxBroker::Policy>
     policy(new SandboxBroker::Policy(*mCommonContentPolicy));
 
   // Read any extra paths that will get write permissions,
--- a/toolkit/xre/nsXREDirProvider.cpp
+++ b/toolkit/xre/nsXREDirProvider.cpp
@@ -705,17 +705,17 @@ nsXREDirProvider::LoadContentProcessTemp
 #endif
 
   return NS_OK;
 }
 
 static bool
 IsContentSandboxDisabled()
 {
-  return !BrowserTabsRemoteAutostart() || (GetEffectiveContentSandboxLevel() < 1);
+  return !BrowserTabsRemoteAutostart() || (!IsContentSandboxEnabled());
 }
 
 //
 // If a content process sandbox temp dir is to be used, returns an nsIFile
 // for the directory. Returns null if the content sandbox is disabled or
 // an error occurs.
 //
 static already_AddRefed<nsIFile>