Bug 1126437 - Add Linux content sandbox level 4 for blocking socket APIs. r=gcp draft
authorJed Davis <jld@mozilla.com>
Thu, 21 Dec 2017 17:32:55 -0700
changeset 724002 51c171ef3d9084e0989daa724dde8cd630af903a
parent 724001 933c53c2d8a32e48526d36234117980bda9d36b9
child 747012 b3f7414ef6af72ee00f6ddfb2f32074ff89b6bf3
push id96596
push userbmo:jld@mozilla.com
push dateWed, 24 Jan 2018 05:35:46 +0000
reviewersgcp
bugs1126437
milestone60.0a1
Bug 1126437 - Add Linux content sandbox level 4 for blocking socket APIs. r=gcp Level 4 is now the default unless audio remoting (media.cubeb.sandbox pref) is disabled. MozReview-Commit-ID: 4jUgiZnJImt
browser/app/profile/firefox.js
security/sandbox/common/SandboxSettings.cpp
security/sandbox/linux/SandboxFilter.cpp
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1091,28 +1091,29 @@ pref("security.sandbox.content.level", 3
 
 #if defined(XP_LINUX) && defined(MOZ_SANDBOX) && defined(MOZ_CONTENT_SANDBOX)
 // This pref is introduced as part of bug 742434, the naming is inspired from
 // its Windows/Mac counterpart, but on Linux it's an integer which means:
 // 0 -> "no sandbox"
 // 1 -> "content sandbox using seccomp-bpf when available"
 // 2 -> "seccomp-bpf + write file broker"
 // 3 -> "seccomp-bpf + read/write file brokering"
+// 4 -> all of the above + network/socket restrictions
 // Content sandboxing on Linux is currently in the stage of
 // 'just getting it enabled', which includes a very permissive whitelist. We
 // enable seccomp-bpf on nightly to see if everything is running, or if we need
 // to whitelist more system calls.
 //
 // So the purpose of this setting is to allow nightly users to disable the
 // sandbox while we fix their problems. This way, they won't have to wait for
 // another nightly release which disables seccomp-bpf again.
 //
 // This setting may not be required anymore once we decide to permanently
 // enable the content sandbox.
-pref("security.sandbox.content.level", 3);
+pref("security.sandbox.content.level", 4);
 pref("security.sandbox.content.write_path_whitelist", "");
 pref("security.sandbox.content.read_path_whitelist", "");
 pref("security.sandbox.content.syscall_whitelist", "");
 #endif
 
 #if defined(XP_MACOSX) || defined(XP_WIN)
 #if defined(MOZ_SANDBOX) && defined(MOZ_CONTENT_SANDBOX)
 // ID (a UUID when set by gecko) that is used to form the name of a
--- a/security/sandbox/common/SandboxSettings.cpp
+++ b/security/sandbox/common/SandboxSettings.cpp
@@ -20,16 +20,23 @@ 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;
   }
 #endif
+#ifdef XP_LINUX
+  // Level 4 and up will break direct access to audio.
+  if (level > 3 && !Preferences::GetBool("media.cubeb.sandbox")) {
+    level = 3;
+  }
+#endif
+
   return level;
 }
 
 bool IsContentSandboxEnabled() {
   return GetEffectiveContentSandboxLevel() > 0;
 }
 
 class SandboxSettings final : public mozISandboxSettings
--- a/security/sandbox/linux/SandboxFilter.cpp
+++ b/security/sandbox/linux/SandboxFilter.cpp
@@ -10,16 +10,17 @@
 #include "Sandbox.h" // for ContentProcessSandboxParams
 #include "SandboxBrokerClient.h"
 #include "SandboxInfo.h"
 #include "SandboxInternal.h"
 #include "SandboxLogging.h"
 #ifdef MOZ_GMP_SANDBOX
 #include "SandboxOpenedFiles.h"
 #endif
+#include "mozilla/Move.h"
 #include "mozilla/PodOperations.h"
 #include "mozilla/TemplateLib.h"
 #include "mozilla/UniquePtr.h"
 
 #include <errno.h>
 #include <fcntl.h>
 #include <linux/ioctl.h>
 #include <linux/ipc.h>
@@ -371,16 +372,26 @@ public:
 // interception in support of a semantic sandboxing layer.  On B2G
 // this is the Android process permission model; on desktop,
 // namespaces and chroot() will be used.
 class ContentSandboxPolicy : public SandboxPolicyCommon {
 private:
   SandboxBrokerClient* mBroker;
   ContentProcessSandboxParams mParams;
 
+  bool BelowLevel(int aLevel) const {
+    return mParams.mLevel < aLevel;
+  }
+  ResultExpr AllowBelowLevel(int aLevel, ResultExpr aOrElse) const {
+    return BelowLevel(aLevel) ? Allow() : Move(aOrElse);
+  }
+  ResultExpr AllowBelowLevel(int aLevel) const {
+    return AllowBelowLevel(aLevel, InvalidSyscall());
+  }
+
   // Trap handlers for filesystem brokering.
   // (The amount of code duplication here could be improved....)
 #ifdef __NR_open
   static intptr_t OpenTrap(ArgsRef aArgs, void* aux) {
     auto broker = static_cast<SandboxBrokerClient*>(aux);
     auto path = reinterpret_cast<const char*>(aArgs.args[0]);
     auto flags = static_cast<int>(aArgs.args[1]);
     return broker->Open(path, flags);
@@ -609,20 +620,25 @@ public:
                      .Default(InvalidSyscall()))
                   .Else(InvalidSyscall()));
     }
 
 #ifdef ANDROID
     case SYS_SOCKET:
       return Some(Error(EACCES));
 #else // #ifdef DESKTOP
+    case SYS_SOCKET: // DANGEROUS
+      // Some things try to get a socket but can work without one,
+      // like sctp_userspace_get_mtu_from_ifn in WebRTC, so this is
+      // silently disallowed.
+      return Some(AllowBelowLevel(4, Error(EACCES)));
+    case SYS_CONNECT: // DANGEROUS
+      return Some(AllowBelowLevel(4));
     case SYS_RECV:
     case SYS_SEND:
-    case SYS_SOCKET: // DANGEROUS
-    case SYS_CONNECT: // DANGEROUS
     case SYS_GETSOCKOPT:
     case SYS_SETSOCKOPT:
     case SYS_GETSOCKNAME:
     case SYS_GETPEERNAME:
     case SYS_SHUTDOWN:
       return Some(Allow());
 #endif
     default: