Bug 1101170 - Move sandbox status info into a separate module. r=kang r=glandium
authorJed Davis <jld@mozilla.com>
Mon, 24 Nov 2014 15:22:13 -0800
changeset 241595 0b3bfc3c27913e0be76dda67798865cf3c270f58
parent 241594 80b929468f358bc1ec0fd6b3bc9b428b9f115518
child 241596 d06d1a469bb1962807e29e036666e06c4f5670e5
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskang, glandium
bugs1101170
milestone36.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 1101170 - Move sandbox status info into a separate module. r=kang r=glandium This changes the interface so that the code which determines the flags can live in one place, but checking the flags doesn't need to call into another library. Also removes the no-op wrappers for Set*Sandbox when disabled at build time; nothing used them, one of them was unusable due to having the wrong type, and all they really accomplish is allowing sloppiness with ifdefs (which could hide actual mistakes).
dom/ipc/ContentChild.cpp
dom/ipc/ContentParent.cpp
dom/media/gmp/GMPChild.cpp
dom/media/gmp/GMPParent.cpp
dom/media/gmp/GMPService.cpp
security/sandbox/linux/Sandbox.cpp
security/sandbox/linux/Sandbox.h
security/sandbox/linux/common/SandboxInfo.cpp
security/sandbox/linux/common/SandboxInfo.h
security/sandbox/linux/common/moz.build
security/sandbox/linux/moz.build
xpcom/base/nsSystemInfo.cpp
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -47,17 +47,20 @@
 #include "mozilla/net/NeckoChild.h"
 #include "mozilla/plugins/PluginModuleParent.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) || defined(XP_MACOSX)
+#elif defined(XP_LINUX)
+#include "mozilla/Sandbox.h"
+#include "mozilla/SandboxInfo.h"
+#elif defined(XP_MACOSX)
 #include "mozilla/Sandbox.h"
 #endif
 #endif
 
 #include "mozilla/unused.h"
 
 #include "mozInlineSpellChecker.h"
 #include "nsIConsoleListener.h"
@@ -1127,20 +1130,20 @@ 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
     // For B2G >= KitKat, sandboxing is mandatory; this has already
     // been enforced by ContentParent::StartUp().
-    MOZ_ASSERT(ContentProcessSandboxStatus() != kSandboxingWouldFail);
+    MOZ_ASSERT(SandboxInfo::Get().CanSandboxContent());
 #else
     // Otherwise, sandboxing is best-effort.
-    if (ContentProcessSandboxStatus() == kSandboxingWouldFail) {
+    if (!SandboxInfo::Get().CanSandboxContent()) {
         return true;
     }
 #endif
     SetContentProcessSandbox();
 #elif defined(XP_WIN)
     nsAdoptingString contentSandboxPref =
         Preferences::GetString("browser.tabs.remote.sandbox");
     if (contentSandboxPref.EqualsLiteral("on")
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -189,17 +189,17 @@ using namespace mozilla::system;
 #ifdef ENABLE_TESTS
 #include "BackgroundChildImpl.h"
 #include "mozilla/ipc/PBackgroundChild.h"
 #include "nsIIPCBackgroundChildCreateCallback.h"
 #endif
 
 
 #if defined(MOZ_CONTENT_SANDBOX) && defined(XP_LINUX)
-#include "mozilla/Sandbox.h"
+#include "mozilla/SandboxInfo.h"
 #endif
 
 #ifdef MOZ_TOOLKIT_SEARCH
 #include "nsIBrowserSearchService.h"
 #endif
 
 #ifdef MOZ_ENABLE_PROFILER_SPS
 #include "nsIProfiler.h"
@@ -694,17 +694,17 @@ ContentParent::StartUp()
 
     if (XRE_GetProcessType() != GeckoProcessType_Default) {
         return;
     }
 
 #if defined(MOZ_CONTENT_SANDBOX) && defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 19
     // Require sandboxing on B2G >= KitKat.  This condition must stay
     // in sync with ContentChild::RecvSetProcessSandbox.
-    if (ContentProcessSandboxStatus() == kSandboxingWouldFail) {
+    if (!SandboxInfo::Get().CanSandboxContent()) {
         // MOZ_CRASH strings are only for debug builds; make sure the
         // message is clear on non-debug builds as well:
         printf_stderr("Sandboxing support is required on this platform.  "
                       "Recompile kernel with CONFIG_SECCOMP_FILTER=y\n");
         MOZ_CRASH("Sandboxing support is required on this platform.");
     }
 #endif
 
--- a/dom/media/gmp/GMPChild.cpp
+++ b/dom/media/gmp/GMPChild.cpp
@@ -28,21 +28,24 @@ using mozilla::dom::CrashReporterChild;
 static const int MAX_PLUGIN_VOUCHER_LENGTH = 500000;
 
 #ifdef XP_WIN
 #include <stdlib.h> // for _exit()
 #else
 #include <unistd.h> // for _exit()
 #endif
 
-#if defined(MOZ_SANDBOX) && defined(XP_WIN)
+#if defined(MOZ_GMP_SANDBOX)
+#if defined(XP_WIN)
 #define TARGET_SANDBOX_EXPORTS
 #include "mozilla/sandboxTarget.h"
-#elif defined (MOZ_GMP_SANDBOX)
-#if defined(XP_LINUX) || defined(XP_MACOSX)
+#elif defined (XP_LINUX)
+#include "mozilla/Sandbox.h"
+#include "mozilla/SandboxInfo.h"
+#elif defined(XP_MACOSX)
 #include "mozilla/Sandbox.h"
 #endif
 #endif
 
 namespace mozilla {
 namespace gmp {
 
 GMPChild::GMPChild()
@@ -355,17 +358,17 @@ GMPChild::PreLoadLibraries(const std::st
 
 #if defined(XP_LINUX)
 class LinuxSandboxStarter : public SandboxStarter {
 public:
   LinuxSandboxStarter(const std::string& aLibPath)
     : mLibPath(aLibPath)
   {}
   virtual void Start() MOZ_OVERRIDE {
-    if (mozilla::MediaPluginSandboxStatus() != mozilla::kSandboxingWouldFail) {
+    if (mozilla::SandboxInfo::Get().CanSandboxMedia()) {
       mozilla::SetMediaPluginSandbox(mLibPath.c_str());
     } else {
       printf_stderr("GMPChild::LoadPluginLibrary: Loading media plugin %s unsandboxed.\n",
                     mLibPath.c_str());
     }
   }
 private:
   std::string mLibPath;
--- a/dom/media/gmp/GMPParent.cpp
+++ b/dom/media/gmp/GMPParent.cpp
@@ -14,17 +14,17 @@
 #include "nsThreadUtils.h"
 #include "nsIRunnable.h"
 #include "mozIGeckoMediaPluginService.h"
 #include "mozilla/unused.h"
 #include "nsIObserverService.h"
 #include "GMPTimerParent.h"
 #include "runnable_utils.h"
 #if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
-#include "mozilla/Sandbox.h"
+#include "mozilla/SandboxInfo.h"
 #endif
 
 #include "mozilla/dom/CrashReporterParent.h"
 using mozilla::dom::CrashReporterParent;
 
 #ifdef MOZ_CRASHREPORTER
 using CrashReporter::AnnotationTable;
 using CrashReporter::GetIDFromMinidump;
@@ -958,17 +958,17 @@ GMPParent::ReadGMPMetaData()
           const nsDependentCSubstring tag(tagTokens.nextToken());
           cap->mAPITags.AppendElement(tag);
         }
       }
     }
 
 #if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
     if (cap->mAPIName.EqualsLiteral("eme-decrypt") &&
-        mozilla::MediaPluginSandboxStatus() == mozilla::kSandboxingWouldFail) {
+        !mozilla::SandboxInfo::Get().CanSandboxMedia()) {
       printf_stderr("GMPParent::ReadGMPMetaData: Plugin \"%s\" is an EME CDM"
                     " but this system can't sandbox it; not loading.\n",
                     mDisplayName.get());
       delete cap;
       return NS_ERROR_FAILURE;
     }
 #endif
 
--- a/dom/media/gmp/GMPService.cpp
+++ b/dom/media/gmp/GMPService.cpp
@@ -20,17 +20,17 @@
 #include "mozilla/unused.h"
 #include "GMPDecryptorParent.h"
 #include "GMPAudioDecoderParent.h"
 #include "nsComponentManagerUtils.h"
 #include "mozilla/Preferences.h"
 #include "runnable_utils.h"
 #include "VideoUtils.h"
 #if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
-#include "mozilla/Sandbox.h"
+#include "mozilla/SandboxInfo.h"
 #endif
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsDirectoryServiceUtils.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsHashKeys.h"
 #include "nsIFile.h"
 
 namespace mozilla {
@@ -474,17 +474,17 @@ GeckoMediaPluginService::GetGMPVideoEnco
 }
 
 NS_IMETHODIMP
 GeckoMediaPluginService::GetGMPDecryptor(nsTArray<nsCString>* aTags,
                                          const nsACString& aNodeId,
                                          GMPDecryptorProxy** aDecryptor)
 {
 #if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
-  if (mozilla::MediaPluginSandboxStatus() == kSandboxingWouldFail) {
+  if (!SandboxInfo::Get().CanSandboxMedia()) {
     NS_WARNING("GeckoMediaPluginService::GetGMPDecryptor: "
                "EME decryption not available without sandboxing support.");
     return NS_ERROR_NOT_AVAILABLE;
   }
 #endif
 
   MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
   NS_ENSURE_ARG(aTags && aTags->Length() > 0);
--- a/security/sandbox/linux/Sandbox.cpp
+++ b/security/sandbox/linux/Sandbox.cpp
@@ -20,16 +20,17 @@
 #include <dirent.h>
 #include <stdlib.h>
 #include <pthread.h>
 #include <errno.h>
 #include <fcntl.h>
 
 #include "mozilla/Atomics.h"
 #include "mozilla/NullPtr.h"
+#include "mozilla/SandboxInfo.h"
 #include "mozilla/unused.h"
 
 #if defined(ANDROID)
 #include "android_ucontext.h"
 #endif
 
 #include "linux_seccomp.h"
 #include "SandboxFilter.h"
@@ -64,59 +65,16 @@ SandboxCrashFunc gSandboxCrashFunc;
 #ifdef MOZ_GMP_SANDBOX
 // For media plugins, we can start the sandbox before we dlopen the
 // module, so we have to pre-open the file and simulate the sandboxed
 // open().
 static int gMediaPluginFileDesc = -1;
 static const char *gMediaPluginFilePath;
 #endif
 
-struct SandboxFlags {
-  bool isSupported;
-#ifdef MOZ_CONTENT_SANDBOX
-  bool isDisabledForContent;
-#endif
-#ifdef MOZ_GMP_SANDBOX
-  bool isDisabledForGMP;
-#endif
-
-  SandboxFlags() {
-    // Allow simulating the absence of seccomp-bpf support, for testing.
-    if (getenv("MOZ_FAKE_NO_SANDBOX")) {
-      isSupported = false;
-    } else {
-      // Determine whether seccomp-bpf is supported by trying to
-      // enable it with an invalid pointer for the filter.  This will
-      // fail with EFAULT if supported and EINVAL if not, without
-      // changing the process's state.
-      if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, nullptr) != -1) {
-        MOZ_CRASH("prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, nullptr)"
-                  " didn't fail");
-      }
-      isSupported = errno == EFAULT;
-    }
-#ifdef MOZ_CONTENT_SANDBOX
-    isDisabledForContent = getenv("MOZ_DISABLE_CONTENT_SANDBOX");
-#endif
-#ifdef MOZ_GMP_SANDBOX
-    isDisabledForGMP = getenv("MOZ_DISABLE_GMP_SANDBOX");
-#endif
-  }
-};
-
-static const SandboxFlags gSandboxFlags;
-
-SandboxFeatureFlags
-GetSandboxFeatureFlags()
-{
-  return gSandboxFlags.isSupported
-    ? kSandboxFeatureSeccompBPF
-    : static_cast<SandboxFeatureFlags>(0);
-}
-
 /**
  * This is the SIGSYS handler function. It is used to report to the user
  * which system call has been denied by Seccomp.
  * This function also makes the process exit as denying the system call
  * will otherwise generally lead to unexpected behavior from the process,
  * since we don't know if all functions will handle such denials gracefully.
  *
  * @see InstallSyscallReporter() function.
@@ -314,17 +272,17 @@ SetThreadSandboxHandler(int signum)
 static void
 BroadcastSetThreadSandbox(SandboxType aType)
 {
   int signum;
   pid_t pid, tid, myTid;
   DIR *taskdp;
   struct dirent *de;
   SandboxFilter filter(&sSetSandboxFilter, aType,
-                       getenv("MOZ_SANDBOX_VERBOSE"));
+                       SandboxInfo::Get().Test(SandboxInfo::kVerbose));
 
   static_assert(sizeof(mozilla::Atomic<int>) == sizeof(int),
                 "mozilla::Atomic<int> isn't represented by an int");
   pid = getpid();
   myTid = syscall(__NR_gettid);
   taskdp = opendir("/proc/self/task");
   if (taskdp == nullptr) {
     SANDBOX_LOG_ERROR("opendir /proc/self/task: %s\n", strerror(errno));
@@ -472,29 +430,22 @@ SetCurrentProcessSandbox(SandboxType aTy
  * Starts the seccomp sandbox for a content process.  Should be called
  * only once, and before any potentially harmful content is loaded.
  *
  * Will normally make the process exit on failure.
 */
 void
 SetContentProcessSandbox()
 {
-  if (gSandboxFlags.isDisabledForContent) {
+  if (!SandboxInfo::Get().Test(SandboxInfo::kEnabledForContent)) {
     return;
   }
 
   SetCurrentProcessSandbox(kSandboxContentProcess);
 }
-
-SandboxStatus
-ContentProcessSandboxStatus()
-{
-  return gSandboxFlags.isDisabledForContent ? kSandboxingDisabled :
-    gSandboxFlags.isSupported ? kSandboxingSupported : kSandboxingWouldFail;
-}
 #endif // MOZ_CONTENT_SANDBOX
 
 #ifdef MOZ_GMP_SANDBOX
 /**
  * Starts the seccomp sandbox for a media plugin process.  Should be
  * called only once, and before any potentially harmful content is
  * loaded -- including the plugin itself, if it's considered untrusted.
  *
@@ -502,34 +453,27 @@ ContentProcessSandboxStatus()
  * read-only after the sandbox starts; it should be the .so file
  * implementing the not-yet-loaded plugin.
  *
  * Will normally make the process exit on failure.
 */
 void
 SetMediaPluginSandbox(const char *aFilePath)
 {
-  if (gSandboxFlags.isDisabledForGMP) {
+  if (!SandboxInfo::Get().Test(SandboxInfo::kEnabledForMedia)) {
     return;
   }
 
   if (aFilePath) {
     gMediaPluginFilePath = strdup(aFilePath);
     gMediaPluginFileDesc = open(aFilePath, O_RDONLY | O_CLOEXEC);
     if (gMediaPluginFileDesc == -1) {
       SANDBOX_LOG_ERROR("failed to open plugin file %s: %s",
                         aFilePath, strerror(errno));
       MOZ_CRASH();
     }
   }
   // Finally, start the sandbox.
   SetCurrentProcessSandbox(kSandboxMediaPlugin);
 }
-
-SandboxStatus
-MediaPluginSandboxStatus()
-{
-  return gSandboxFlags.isDisabledForGMP ? kSandboxingDisabled :
-    gSandboxFlags.isSupported ? kSandboxingSupported : kSandboxingWouldFail;
-}
 #endif // MOZ_GMP_SANDBOX
 
 } // namespace mozilla
--- a/security/sandbox/linux/Sandbox.h
+++ b/security/sandbox/linux/Sandbox.h
@@ -4,62 +4,29 @@
  * 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/. */
 
 #ifndef mozilla_Sandbox_h
 #define mozilla_Sandbox_h
 
 #include "mozilla/Types.h"
 
+// This defines the entry points for a content process to start
+// sandboxing itself.  See also common/SandboxInfo.h for what parts of
+// sandboxing are enabled/supported.
+
 namespace mozilla {
 
-// Whether a given type of sandboxing is available, and why not:
-enum SandboxStatus {
-  // Sandboxing is enabled in Gecko but not available on this system;
-  // trying to start the sandbox will crash:
-  kSandboxingWouldFail,
-  // Sandboxing is enabled in Gecko and is available:
-  kSandboxingSupported,
-  // Sandboxing is disabled, either at compile-time or at run-time;
-  // trying to start the sandbox is a no-op:
-  kSandboxingDisabled,
-};
-
-
 #ifdef MOZ_CONTENT_SANDBOX
-// Disabled by setting env var MOZ_DISABLE_CONTENT_SANDBOX.
-MOZ_EXPORT SandboxStatus ContentProcessSandboxStatus();
+// Call only if SandboxInfo::CanSandboxContent() returns true.
+// (No-op if MOZ_DISABLE_CONTENT_SANDBOX is set.)
 MOZ_EXPORT void SetContentProcessSandbox();
-#else
-static inline SandboxStatus ContentProcessSandboxStatus()
-{
-  return kSandboxingDisabled;
-}
-static inline void SetContentProcessSandbox()
-{
-}
 #endif
 
 #ifdef MOZ_GMP_SANDBOX
-// Disabled by setting env var MOZ_DISABLE_GMP_SANDBOX.
-MOZ_EXPORT SandboxStatus MediaPluginSandboxStatus();
+// Call only if SandboxInfo::CanSandboxMedia() returns true.
+// (No-op if MOZ_DISABLE_GMP_SANDBOX is set.)
 MOZ_EXPORT void SetMediaPluginSandbox(const char *aFilePath);
-#else
-static inline SandboxStatus MediaPluginSandboxStatus()
-{
-  return kSandboxingDisabled;
-}
-static inline void SetMediaPluginSandbox()
-{
-}
 #endif
 
-// System-level security features which are relevant to our sandboxing
-// and which aren't available on all Linux systems supported by Gecko.
-enum SandboxFeatureFlags {
-  kSandboxFeatureSeccompBPF = 1 << 0,
-};
-
-MOZ_EXPORT SandboxFeatureFlags GetSandboxFeatureFlags();
-
 } // namespace mozilla
 
 #endif // mozilla_Sandbox_h
new file mode 100644
--- /dev/null
+++ b/security/sandbox/linux/common/SandboxInfo.cpp
@@ -0,0 +1,58 @@
+/* -*- 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 "SandboxInfo.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/prctl.h>
+
+#include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
+#include "mozilla/Assertions.h"
+#include "mozilla/NullPtr.h"
+
+namespace mozilla {
+
+/* static */
+const SandboxInfo SandboxInfo::sSingleton = SandboxInfo();
+
+SandboxInfo::SandboxInfo() {
+  int flags = 0;
+  static_assert(sizeof(flags) >= sizeof(Flags), "enum Flags fits in an int");
+
+  // Allow simulating the absence of seccomp-bpf support, for testing.
+  if (!getenv("MOZ_FAKE_NO_SANDBOX")) {
+    // Determine whether seccomp-bpf is supported by trying to
+    // enable it with an invalid pointer for the filter.  This will
+    // fail with EFAULT if supported and EINVAL if not, without
+    // changing the process's state.
+    if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, nullptr) != -1) {
+      MOZ_CRASH("prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, nullptr)"
+                " didn't fail");
+    }
+    if (errno == EFAULT) {
+      flags |= kHasSeccompBPF;
+    }
+  }
+
+#ifdef MOZ_CONTENT_SANDBOX
+  if (!getenv("MOZ_DISABLE_CONTENT_SANDBOX")) {
+    flags |= kEnabledForContent;
+  }
+#endif
+#ifdef MOZ_GMP_SANDBOX
+  if (!getenv("MOZ_DISABLE_GMP_SANDBOX")) {
+    flags |= kEnabledForMedia;
+  }
+#endif
+  if (getenv("MOZ_SANDBOX_VERBOSE")) {
+    flags |= kVerbose;
+  }
+
+  mFlags = static_cast<Flags>(flags);
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/security/sandbox/linux/common/SandboxInfo.h
@@ -0,0 +1,57 @@
+/* -*- 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/. */
+
+#ifndef mozilla_SandboxInfo_h
+#define mozilla_SandboxInfo_h
+
+#include "mozilla/Types.h"
+
+// Information on what parts of sandboxing are enabled in this build
+// and/or supported by the system.
+
+namespace mozilla {
+
+class SandboxInfo {
+public:
+  // No need to prevent copying; this is essentially just a const int.
+  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.
+    kEnabledForContent = 1 << 1,
+    // Config flag MOZ_GMP_SANDBOX; env var MOZ_DISABLE_GMP_SANDBOX.
+    kEnabledForMedia   = 1 << 2,
+    // Env var MOZ_SANDBOX_VERBOSE.
+    kVerbose           = 1 << 3,
+  };
+
+  bool Test(Flags aFlag) const { return (mFlags & aFlag) == aFlag; }
+
+  // Returns true if SetContentProcessSandbox may be called.
+  bool CanSandboxContent() const
+  {
+    return !Test(kEnabledForContent) || Test(kHasSeccompBPF);
+  }
+
+  // Returns true if SetMediaPluginSandbox may be called.
+  bool CanSandboxMedia() const
+  {
+    return !Test(kEnabledForMedia) || Test(kHasSeccompBPF);
+  }
+private:
+  enum Flags mFlags;
+  static MOZ_EXPORT const SandboxInfo sSingleton;
+  SandboxInfo();
+};
+
+} // namespace mozilla
+
+#endif // mozilla_SandboxInfo_h
new file mode 100644
--- /dev/null
+++ b/security/sandbox/linux/common/moz.build
@@ -0,0 +1,21 @@
+# -*- Mode: python; python-indent: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+FAIL_ON_WARNINGS = True
+
+EXPORTS.mozilla += [
+    'SandboxInfo.h',
+]
+
+SOURCES += [
+    'SandboxInfo.cpp',
+]
+
+LOCAL_INCLUDES += [
+    '/security/sandbox/chromium'
+]
+
+FINAL_LIBRARY = 'mozsandbox'
--- a/security/sandbox/linux/moz.build
+++ b/security/sandbox/linux/moz.build
@@ -38,10 +38,11 @@ LOCAL_INCLUDES += ['/security/sandbox']
 
 if CONFIG['OS_TARGET'] != 'Android':
     # Needed for clock_gettime with glibc < 2.17:
     OS_LIBS += [
         'rt',
     ]
 
 DIRS += [
+    'common',
     'glue',
 ]
--- a/xpcom/base/nsSystemInfo.cpp
+++ b/xpcom/base/nsSystemInfo.cpp
@@ -40,17 +40,17 @@ using namespace mozilla::widget::android
 
 #ifdef ANDROID
 extern "C" {
 NS_EXPORT int android_sdk_version;
 }
 #endif
 
 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
-#include "mozilla/Sandbox.h"
+#include "mozilla/SandboxInfo.h"
 #endif
 
 // Slot for NS_InitXPCOM2 to pass information to nsSystemInfo::Init.
 // Only set to nonzero (potentially) if XP_UNIX.  On such systems, the
 // system call to discover the appropriate value is not thread-safe,
 // so we must call it before going multithreaded, but nsSystemInfo::Init
 // only happens well after that point.
 uint32_t nsSystemInfo::gUserUmask = 0;
@@ -352,30 +352,29 @@ nsSystemInfo::Init()
   const nsAdoptingString& b2g_version =
     mozilla::Preferences::GetString("b2g.version");
   if (b2g_version) {
     SetPropertyAsAString(NS_LITERAL_STRING("version"), b2g_version);
   }
 #endif
 
 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
-  SandboxFeatureFlags sandboxFlags = GetSandboxFeatureFlags();
-  SetPropertyAsBool(NS_LITERAL_STRING("hasSeccompBPF"),
-                    sandboxFlags & kSandboxFeatureSeccompBPF);
+  SandboxInfo sandInfo = SandboxInfo::Get();
 
-  SandboxStatus sandboxContent = ContentProcessSandboxStatus();
-  if (sandboxContent != kSandboxingDisabled) {
+  SetPropertyAsBool(NS_LITERAL_STRING("hasSeccompBPF"),
+                    sandInfo.Test(SandboxInfo::kHasSeccompBPF));
+
+  if (sandInfo.Test(SandboxInfo::kEnabledForContent)) {
     SetPropertyAsBool(NS_LITERAL_STRING("canSandboxContent"),
-                      sandboxContent != kSandboxingWouldFail);
+                      sandInfo.CanSandboxContent());
   }
 
-  SandboxStatus sandboxMedia = MediaPluginSandboxStatus();
-  if (sandboxMedia != kSandboxingDisabled) {
+  if (sandInfo.Test(SandboxInfo::kEnabledForMedia)) {
     SetPropertyAsBool(NS_LITERAL_STRING("canSandboxMedia"),
-                      sandboxMedia != kSandboxingWouldFail);
+                      sandInfo.CanSandboxMedia());
   }
 #endif // XP_LINUX && MOZ_SANDBOX
 
   return NS_OK;
 }
 
 void
 nsSystemInfo::SetInt32Property(const nsAString& aPropertyName,