Bug 1450740 - Don't sandbox network namespace when X11 named sockets aren't accessible. r=gcp
MozReview-Commit-ID: KiL4GwMms3a
--- a/security/sandbox/linux/launch/SandboxLaunch.cpp
+++ b/security/sandbox/linux/launch/SandboxLaunch.cpp
@@ -27,16 +27,17 @@
#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 "nsDebug.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
@@ -81,24 +82,40 @@ IsDisplayLocal()
int domain;
socklen_t optlen = static_cast<socklen_t>(sizeof(domain));
int rv = getsockopt(xSocketFd, SOL_SOCKET, SO_DOMAIN, &domain, &optlen);
if (NS_WARN_IF(rv != 0)) {
return false;
}
MOZ_RELEASE_ASSERT(static_cast<size_t>(optlen) == sizeof(domain));
- // There's one more wrinkle here: the network namespace also
- // controls "abstract namespace" addresses in the Unix domain.
- // Xorg seems to listen on both abstract and normal addresses, but
- // prefers abstract. This mean that if there exists a server that
- // uses only the abstract namespace, then it will break and we
- // won't be able to detect that ahead of time. So, hopefully it
- // does not exist.
- return domain == AF_LOCAL;
+ if (domain != AF_LOCAL) {
+ return false;
+ }
+ // There's one more complication: Xorg listens on named sockets
+ // (actual filesystem nodes) as well as abstract addresses (opaque
+ // octet strings scoped to the network namespace; this is a Linux
+ // extension).
+ //
+ // Inside a container environment (e.g., when running as a Snap
+ // package), it's possible that only the abstract addresses are
+ // accessible. In that case, the display must be considered
+ // remote. See also bug 1450740.
+ //
+ // Unfortunately, the Xorg client libraries prefer the abstract
+ // addresses, so this isn't directly detectable by inspecting the
+ // parent process's socket. Instead, this checks for the
+ // directory the sockets are stored in, which typically won't
+ // exist in a container with a private /tmp that isn't running its
+ // own X server.
+ if (access("/tmp/.X11-unix", X_OK) != 0) {
+ NS_ERROR("/tmp/.X11-unix is inaccessible; can't isolate network"
+ " namespace in content processes");
+ return false;
+ }
}
#endif
// Assume that other backends (e.g., Wayland) will not use the
// network namespace.
return true;
}