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
--- 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: