Bug 1376910 - Remove SysV IPC access from Linux content sandbox when possible. r=gcp
There are a few things that use SysV IPC, which we discovered the last
time we tried to do this, which need to be accomodated:
1. The ALSA dmix plugin; if the build has ALSA support (off by default)
and if audio remoting is disabled, SysV IPC is allowed.
2. ATI/AMD's old proprietary graphics driver (fglrx), which is obsolete
and doesn't support newer hardware, but still has users; if it's
detected, SysV IPC is allowed.
3. Graphics libraries trying to use the MIT-SHM extension; this is
already turned off for other reasons (see
bug 1271100), but that shim
seems to not load early enough in some cases, so it's copied into
libmozsandbox, which is preloaded before anything else in LD_PRELOAD.
Also, msgget is now blocked in all cases; the only case it was known
to be used involved ESET antivirus, which is now handled specially
(
bug 1362601). In any case, the seccomp-bpf policy has never allowed
actually *using* message queues, so creating them is not very useful.
MozReview-Commit-ID: 5bOOQcXFd9U
--- a/security/sandbox/linux/SandboxFilter.cpp
+++ b/security/sandbox/linux/SandboxFilter.cpp
@@ -14,16 +14,17 @@
#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 "prenv.h"
#include <errno.h>
#include <fcntl.h>
#include <linux/ioctl.h>
#include <linux/ipc.h>
#include <linux/net.h>
#include <linux/prctl.h>
#include <linux/sched.h>
@@ -371,16 +372,17 @@ public:
// on its own; its purpose is attack surface reduction and syscall
// 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 mAllowSysV;
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 {
@@ -589,16 +591,17 @@ private:
return rv;
}
public:
ContentSandboxPolicy(SandboxBrokerClient* aBroker,
ContentProcessSandboxParams&& aParams)
: mBroker(aBroker)
, mParams(Move(aParams))
+ , mAllowSysV(PR_GetEnv("MOZ_SANDBOX_ALLOW_SYSV") != nullptr)
{ }
~ContentSandboxPolicy() override = default;
Maybe<ResultExpr> EvaluateSocketCall(int aCall) const override {
switch(aCall) {
case SYS_RECVFROM:
case SYS_SENDTO:
@@ -655,18 +658,20 @@ public:
// anymore; this needs to be studied.
case SHMGET:
case SHMCTL:
case SHMAT:
case SHMDT:
case SEMGET:
case SEMCTL:
case SEMOP:
- case MSGGET:
- return Some(Allow());
+ if (mAllowSysV) {
+ return Some(Allow());
+ }
+ return SandboxPolicyCommon::EvaluateIpcCall(aCall);
default:
return SandboxPolicyCommon::EvaluateIpcCall(aCall);
}
}
#endif
#ifdef MOZ_PULSEAUDIO
ResultExpr PrctlPolicy() const override {
--- a/security/sandbox/linux/SandboxHooks.cpp
+++ b/security/sandbox/linux/SandboxHooks.cpp
@@ -9,16 +9,19 @@
#include <dlfcn.h>
#include <signal.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/inotify.h>
+#ifdef MOZ_X11
+#include <X11/Xlib.h>
+#endif
// Signal number used to enable seccomp on each thread.
extern mozilla::Atomic<int> gSeccompTsyncBroadcastSignum;
static bool
SigSetNeedsFixup(const sigset_t* aSet)
{
int tsyncSignum = gSeccompTsyncBroadcastSignum;
@@ -116,8 +119,22 @@ inotify_init(void)
}
extern "C" MOZ_EXPORT int
inotify_init1(int flags)
{
errno = ENOSYS;
return -1;
}
+
+#ifdef MOZ_X11
+// We're already preventing the use of X11 MIT-SHM like this in
+// widget/gtk/mozgtk/mozgtk.c because of bug 1271100, but that's not
+// quite enough: sometimes libXext can be preloaded, so we have to
+// defeat that with our own preload library. (With just the mozgtk
+// interposition, we saw crashes when we blocked the SysV IPC
+// syscalls; see bug 1376910 comment #14.)
+extern "C" MOZ_EXPORT Bool
+XShmQueryExtension(Display* aDisplay)
+{
+ return False;
+}
+#endif
--- a/security/sandbox/linux/launch/SandboxLaunch.cpp
+++ b/security/sandbox/linux/launch/SandboxLaunch.cpp
@@ -16,24 +16,28 @@
#include "LinuxCapabilities.h"
#include "LinuxSched.h"
#include "SandboxChrootProto.h"
#include "SandboxInfo.h"
#include "SandboxLogging.h"
#include "base/eintr_wrapper.h"
#include "base/strings/safe_sprintf.h"
+#include "mozilla/Array.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/Move.h"
#include "mozilla/Preferences.h"
#include "mozilla/SandboxReporter.h"
#include "mozilla/SandboxSettings.h"
+#include "mozilla/Services.h"
#include "mozilla/Unused.h"
+#include "nsCOMPtr.h"
+#include "nsIGfxInfo.h"
#include "nsString.h"
#include "nsThreadUtils.h"
#include "prenv.h"
#include "sandbox/linux/system_headers/linux_syscalls.h"
#ifdef MOZ_X11
#ifndef MOZ_WIDGET_GTK
#error "Unknown toolkit"
@@ -93,16 +97,48 @@ IsDisplayLocal()
}
#endif
// Assume that other backends (e.g., Wayland) will not use the
// network namespace.
return true;
}
+// Content processes may need direct access to SysV IPC in certain
+// uncommon use cases: if using fglrx GPU drivers (officially obsolete
+// but still in use), or the ALSA dmix plugin without cubeb remoting.
+static bool
+ContentNeedsSysVIPC()
+{
+#ifdef MOZ_ALSA
+ if (!Preferences::GetBool("media.cubeb.sandbox")) {
+ return true;
+ }
+#endif
+ nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
+ nsAutoString vendorID;
+ static const Array<nsresult (nsIGfxInfo::*)(nsAString&), 2> kMethods = {
+ &nsIGfxInfo::GetAdapterVendorID,
+ &nsIGfxInfo::GetAdapterVendorID2,
+ };
+ for (const auto method : kMethods) {
+ if (NS_SUCCEEDED((gfxInfo->*method)(vendorID))) {
+ // This test is based on telemetry data. The proprietary ATI
+ // drivers seem to use this vendor string, including for some
+ // newer devices that have AMD branding in the device name.
+ // The open-source drivers integrated into Mesa appear to use
+ // the vendor ID "X.Org" instead.
+ if (vendorID.EqualsLiteral("ATI Technologies Inc.")) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
static void
PreloadSandboxLib(base::environment_map* aEnv)
{
// Preload libmozsandbox.so so that sandbox-related interpositions
// can be defined there instead of in the executable.
// (This could be made conditional on intent to use sandboxing, but
// it's harmless for non-sandboxed processes.)
nsAutoCString preload;
@@ -211,18 +247,26 @@ SandboxLaunchPrepare(GeckoProcessType aT
if (level >= 1) {
canChroot = true;
flags |= CLONE_NEWNET | CLONE_NEWIPC;
}
break;
#endif
#ifdef MOZ_CONTENT_SANDBOX
case GeckoProcessType_Content:
- // TODO: CLONE_NEWIPC (bug 1376910) if not fglrx and level >= 1,
- // once the XShm detection shim is fixed.
+ if (level >= 1) {
+ static const bool needSysV = ContentNeedsSysVIPC();
+ if (needSysV) {
+ // Tell the child process so it can adjust its seccomp-bpf
+ // policy.
+ aOptions->env_map["MOZ_SANDBOX_ALLOW_SYSV"] = "1";
+ } else {
+ flags |= CLONE_NEWIPC;
+ }
+ }
if (level >= 4) {
canChroot = true;
// Unshare network namespace if allowed by graphics; see
// function definition above for details. (The display
// local-ness is cached because it won't change.)
static const bool isDisplayLocal = IsDisplayLocal();
if (isDisplayLocal) {
--- a/security/sandbox/linux/launch/moz.build
+++ b/security/sandbox/linux/launch/moz.build
@@ -21,12 +21,15 @@ LOCAL_INCLUDES += [
'/security/sandbox/chromium',
'/security/sandbox/linux',
]
USE_LIBS += [
'mozsandbox',
]
+if CONFIG['MOZ_ALSA']:
+ DEFINES['MOZ_ALSA'] = True
+
# For the X11 socket domain inspection in SandboxLaunch:
CXXFLAGS += CONFIG['TK_CFLAGS']
FINAL_LIBRARY = 'xul'