зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 5 changesets (bug 1769182) for causing mochitest failures on browser_sandbox_test.js. CLOSED TREE
Backed out changeset f5b71a28f28b (bug 1769182) Backed out changeset 7a64faec004f (bug 1769182) Backed out changeset c7833370362a (bug 1769182) Backed out changeset b91adae9bb59 (bug 1769182) Backed out changeset cf7bb9b7414d (bug 1769182)
This commit is contained in:
Родитель
accee09e1b
Коммит
cf3fad08ff
|
@ -420,13 +420,6 @@ GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType,
|
|||
if (NS_SUCCEEDED(rv)) {
|
||||
contentTempDir->GetNativePath(mTmpDirName);
|
||||
}
|
||||
} else if (aProcessType == GeckoProcessType_RDD) {
|
||||
// The RDD process makes limited use of EGL. If Mesa's shader
|
||||
// cache is enabled and the directory isn't explicitly set, then
|
||||
// it will try to getpwuid() the user which can cause problems
|
||||
// with sandboxing. Because we shouldn't need shader caching in
|
||||
// this process, we just disable the cache to prevent that.
|
||||
mLaunchOptions->env_map["MESA_GLSL_CACHE_DISABLE"] = "true";
|
||||
}
|
||||
#endif
|
||||
#if defined(MOZ_ENABLE_FORKSERVER)
|
||||
|
|
|
@ -125,12 +125,27 @@ namespace mozilla {
|
|||
// denied if no broker client is provided by the concrete class.
|
||||
class SandboxPolicyCommon : public SandboxPolicyBase {
|
||||
protected:
|
||||
// Subclasses can assign these in their constructors to loosen the
|
||||
// default settings.
|
||||
enum class ShmemUsage : uint8_t {
|
||||
MAY_CREATE,
|
||||
ONLY_USE,
|
||||
};
|
||||
|
||||
enum class AllowUnsafeSocketPair : uint8_t {
|
||||
NO,
|
||||
YES,
|
||||
};
|
||||
|
||||
SandboxBrokerClient* mBroker = nullptr;
|
||||
bool mMayCreateShmem = false;
|
||||
bool mAllowUnsafeSocketPair = false;
|
||||
bool mBrokeredConnect = false; // Can connect() be brokered?
|
||||
|
||||
explicit SandboxPolicyCommon(SandboxBrokerClient* aBroker,
|
||||
ShmemUsage aShmemUsage,
|
||||
AllowUnsafeSocketPair aAllowUnsafeSocketPair)
|
||||
: mBroker(aBroker),
|
||||
mMayCreateShmem(aShmemUsage == ShmemUsage::MAY_CREATE),
|
||||
mAllowUnsafeSocketPair(aAllowUnsafeSocketPair ==
|
||||
AllowUnsafeSocketPair::YES) {}
|
||||
|
||||
SandboxPolicyCommon() = default;
|
||||
|
||||
|
@ -536,120 +551,6 @@ class SandboxPolicyCommon : public SandboxPolicyBase {
|
|||
#endif
|
||||
}
|
||||
|
||||
// This just needs to return something to stand in for the
|
||||
// unconnected socket until ConnectTrap, below, and keep track of
|
||||
// the socket type somehow. Half a socketpair *is* a socket, so it
|
||||
// should result in minimal confusion in the caller.
|
||||
static intptr_t FakeSocketTrapCommon(int domain, int type, int protocol) {
|
||||
int fds[2];
|
||||
// X11 client libs will still try to getaddrinfo() even for a
|
||||
// local connection. Also, WebRTC still has vestigial network
|
||||
// code trying to do things in the content process. Politely tell
|
||||
// them no.
|
||||
if (domain != AF_UNIX) {
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
if (socketpair(domain, type, protocol, fds) != 0) {
|
||||
return -errno;
|
||||
}
|
||||
close(fds[1]);
|
||||
return fds[0];
|
||||
}
|
||||
|
||||
static intptr_t FakeSocketTrap(ArgsRef aArgs, void* aux) {
|
||||
return FakeSocketTrapCommon(static_cast<int>(aArgs.args[0]),
|
||||
static_cast<int>(aArgs.args[1]),
|
||||
static_cast<int>(aArgs.args[2]));
|
||||
}
|
||||
|
||||
static intptr_t FakeSocketTrapLegacy(ArgsRef aArgs, void* aux) {
|
||||
const auto innerArgs = reinterpret_cast<unsigned long*>(aArgs.args[1]);
|
||||
|
||||
return FakeSocketTrapCommon(static_cast<int>(innerArgs[0]),
|
||||
static_cast<int>(innerArgs[1]),
|
||||
static_cast<int>(innerArgs[2]));
|
||||
}
|
||||
|
||||
static Maybe<int> DoGetSockOpt(int fd, int optname) {
|
||||
int optval;
|
||||
socklen_t optlen = sizeof(optval);
|
||||
|
||||
if (getsockopt(fd, SOL_SOCKET, optname, &optval, &optlen) != 0) {
|
||||
return Nothing();
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(static_cast<size_t>(optlen) == sizeof(optval));
|
||||
return Some(optval);
|
||||
}
|
||||
|
||||
// Substitute the newly connected socket from the broker for the
|
||||
// original socket. This is meant to be used on a fd from
|
||||
// FakeSocketTrap, above, but it should also work to simulate
|
||||
// re-connect()ing a real connected socket.
|
||||
//
|
||||
// Warning: This isn't quite right if the socket is dup()ed, because
|
||||
// other duplicates will still be the original socket, but hopefully
|
||||
// nothing we're dealing with does that.
|
||||
static intptr_t ConnectTrapCommon(SandboxBrokerClient* aBroker, int aFd,
|
||||
const struct sockaddr_un* aAddr,
|
||||
socklen_t aLen) {
|
||||
if (aFd < 0) {
|
||||
return -EBADF;
|
||||
}
|
||||
const auto maybeDomain = DoGetSockOpt(aFd, SO_DOMAIN);
|
||||
if (!maybeDomain) {
|
||||
return -errno;
|
||||
}
|
||||
if (*maybeDomain != AF_UNIX) {
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
const auto maybeType = DoGetSockOpt(aFd, SO_TYPE);
|
||||
if (!maybeType) {
|
||||
return -errno;
|
||||
}
|
||||
const int oldFlags = fcntl(aFd, F_GETFL);
|
||||
if (oldFlags == -1) {
|
||||
return -errno;
|
||||
}
|
||||
const int newFd = aBroker->Connect(aAddr, aLen, *maybeType);
|
||||
if (newFd < 0) {
|
||||
return newFd;
|
||||
}
|
||||
// Copy over the nonblocking flag. The connect() won't be
|
||||
// nonblocking in that case, but that shouldn't matter for
|
||||
// AF_UNIX. The other fcntl-settable flags are either irrelevant
|
||||
// for sockets (e.g., O_APPEND) or would be blocked by this
|
||||
// seccomp-bpf policy, so they're ignored.
|
||||
if (fcntl(newFd, F_SETFL, oldFlags & O_NONBLOCK) != 0) {
|
||||
close(newFd);
|
||||
return -errno;
|
||||
}
|
||||
if (dup2(newFd, aFd) < 0) {
|
||||
close(newFd);
|
||||
return -errno;
|
||||
}
|
||||
close(newFd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static intptr_t ConnectTrap(ArgsRef aArgs, void* aux) {
|
||||
typedef const struct sockaddr_un* AddrPtr;
|
||||
|
||||
return ConnectTrapCommon(static_cast<SandboxBrokerClient*>(aux),
|
||||
static_cast<int>(aArgs.args[0]),
|
||||
reinterpret_cast<AddrPtr>(aArgs.args[1]),
|
||||
static_cast<socklen_t>(aArgs.args[2]));
|
||||
}
|
||||
|
||||
static intptr_t ConnectTrapLegacy(ArgsRef aArgs, void* aux) {
|
||||
const auto innerArgs = reinterpret_cast<unsigned long*>(aArgs.args[1]);
|
||||
typedef const struct sockaddr_un* AddrPtr;
|
||||
|
||||
return ConnectTrapCommon(static_cast<SandboxBrokerClient*>(aux),
|
||||
static_cast<int>(innerArgs[0]),
|
||||
reinterpret_cast<AddrPtr>(innerArgs[1]),
|
||||
static_cast<socklen_t>(innerArgs[2]));
|
||||
}
|
||||
|
||||
public:
|
||||
ResultExpr InvalidSyscall() const override {
|
||||
return Trap(BlockedSyscallTrap, nullptr);
|
||||
|
@ -701,14 +602,6 @@ class SandboxPolicyCommon : public SandboxPolicyBase {
|
|||
switch (aCall) {
|
||||
case SYS_RECVMSG:
|
||||
case SYS_SENDMSG:
|
||||
// These next four aren't needed for IPC or other core
|
||||
// functionality at the time of this writing, but they're
|
||||
// subsets of recvmsg/sendmsg so there's nothing gained by not
|
||||
// allowing them here (and simplifying subclasses).
|
||||
case SYS_RECVFROM:
|
||||
case SYS_SENDTO:
|
||||
case SYS_RECV:
|
||||
case SYS_SEND:
|
||||
return Some(Allow());
|
||||
|
||||
case SYS_SOCKETPAIR: {
|
||||
|
@ -755,33 +648,11 @@ class SandboxPolicyCommon : public SandboxPolicyBase {
|
|||
Arg<int> level(1), optname(2);
|
||||
// SO_SNDBUF is used by IPC to avoid constructing
|
||||
// unnecessarily large gather arrays for `sendmsg`.
|
||||
//
|
||||
// SO_DOMAIN and SO_TYPE are needed for connect() brokering,
|
||||
// but they're harmless even when it's not enabled.
|
||||
return Some(If(AllOf(level == SOL_SOCKET,
|
||||
AnyOf(optname == SO_SNDBUF, optname == SO_DOMAIN,
|
||||
optname == SO_TYPE)),
|
||||
Allow())
|
||||
.Else(InvalidSyscall()));
|
||||
return Some(
|
||||
If(AllOf(level == SOL_SOCKET, optname == SO_SNDBUF), Allow())
|
||||
.Else(InvalidSyscall()));
|
||||
}
|
||||
|
||||
// These two cases are for connect() brokering, if enabled.
|
||||
case SYS_SOCKET:
|
||||
if (mBrokeredConnect) {
|
||||
const auto trapFn = aHasArgs ? FakeSocketTrap : FakeSocketTrapLegacy;
|
||||
MOZ_ASSERT(mBroker);
|
||||
return Some(Trap(trapFn, mBroker));
|
||||
}
|
||||
return Nothing();
|
||||
|
||||
case SYS_CONNECT:
|
||||
if (mBrokeredConnect) {
|
||||
const auto trapFn = aHasArgs ? ConnectTrap : ConnectTrapLegacy;
|
||||
MOZ_ASSERT(mBroker);
|
||||
return Some(Trap(trapFn, mBroker));
|
||||
}
|
||||
return Nothing();
|
||||
|
||||
default:
|
||||
return Nothing();
|
||||
}
|
||||
|
@ -1153,12 +1024,6 @@ class SandboxPolicyCommon : public SandboxPolicyBase {
|
|||
.Else(SandboxPolicyBase::EvaluateSyscall(sysno));
|
||||
}
|
||||
|
||||
CASES_FOR_dup2: // See ConnectTrapCommon
|
||||
if (mBrokeredConnect) {
|
||||
return Allow();
|
||||
}
|
||||
return SandboxPolicyBase::EvaluateSyscall(sysno);
|
||||
|
||||
#ifdef MOZ_ASAN
|
||||
// ASAN's error reporter wants to know if stderr is a tty.
|
||||
case __NR_ioctl: {
|
||||
|
@ -1246,23 +1111,136 @@ class ContentSandboxPolicy : public SandboxPolicyCommon {
|
|||
return rv;
|
||||
}
|
||||
|
||||
// This just needs to return something to stand in for the
|
||||
// unconnected socket until ConnectTrap, below, and keep track of
|
||||
// the socket type somehow. Half a socketpair *is* a socket, so it
|
||||
// should result in minimal confusion in the caller.
|
||||
static intptr_t FakeSocketTrapCommon(int domain, int type, int protocol) {
|
||||
int fds[2];
|
||||
// X11 client libs will still try to getaddrinfo() even for a
|
||||
// local connection. Also, WebRTC still has vestigial network
|
||||
// code trying to do things in the content process. Politely tell
|
||||
// them no.
|
||||
if (domain != AF_UNIX) {
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
if (socketpair(domain, type, protocol, fds) != 0) {
|
||||
return -errno;
|
||||
}
|
||||
close(fds[1]);
|
||||
return fds[0];
|
||||
}
|
||||
|
||||
static intptr_t FakeSocketTrap(ArgsRef aArgs, void* aux) {
|
||||
return FakeSocketTrapCommon(static_cast<int>(aArgs.args[0]),
|
||||
static_cast<int>(aArgs.args[1]),
|
||||
static_cast<int>(aArgs.args[2]));
|
||||
}
|
||||
|
||||
static intptr_t FakeSocketTrapLegacy(ArgsRef aArgs, void* aux) {
|
||||
const auto innerArgs = reinterpret_cast<unsigned long*>(aArgs.args[1]);
|
||||
|
||||
return FakeSocketTrapCommon(static_cast<int>(innerArgs[0]),
|
||||
static_cast<int>(innerArgs[1]),
|
||||
static_cast<int>(innerArgs[2]));
|
||||
}
|
||||
|
||||
static Maybe<int> DoGetSockOpt(int fd, int optname) {
|
||||
int optval;
|
||||
socklen_t optlen = sizeof(optval);
|
||||
|
||||
if (getsockopt(fd, SOL_SOCKET, optname, &optval, &optlen) != 0) {
|
||||
return Nothing();
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(static_cast<size_t>(optlen) == sizeof(optval));
|
||||
return Some(optval);
|
||||
}
|
||||
|
||||
// Substitute the newly connected socket from the broker for the
|
||||
// original socket. This is meant to be used on a fd from
|
||||
// FakeSocketTrap, above, but it should also work to simulate
|
||||
// re-connect()ing a real connected socket.
|
||||
//
|
||||
// Warning: This isn't quite right if the socket is dup()ed, because
|
||||
// other duplicates will still be the original socket, but hopefully
|
||||
// nothing we're dealing with does that.
|
||||
static intptr_t ConnectTrapCommon(SandboxBrokerClient* aBroker, int aFd,
|
||||
const struct sockaddr_un* aAddr,
|
||||
socklen_t aLen) {
|
||||
if (aFd < 0) {
|
||||
return -EBADF;
|
||||
}
|
||||
const auto maybeDomain = DoGetSockOpt(aFd, SO_DOMAIN);
|
||||
if (!maybeDomain) {
|
||||
return -errno;
|
||||
}
|
||||
if (*maybeDomain != AF_UNIX) {
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
const auto maybeType = DoGetSockOpt(aFd, SO_TYPE);
|
||||
if (!maybeType) {
|
||||
return -errno;
|
||||
}
|
||||
const int oldFlags = fcntl(aFd, F_GETFL);
|
||||
if (oldFlags == -1) {
|
||||
return -errno;
|
||||
}
|
||||
const int newFd = aBroker->Connect(aAddr, aLen, *maybeType);
|
||||
if (newFd < 0) {
|
||||
return newFd;
|
||||
}
|
||||
// Copy over the nonblocking flag. The connect() won't be
|
||||
// nonblocking in that case, but that shouldn't matter for
|
||||
// AF_UNIX. The other fcntl-settable flags are either irrelevant
|
||||
// for sockets (e.g., O_APPEND) or would be blocked by this
|
||||
// seccomp-bpf policy, so they're ignored.
|
||||
if (fcntl(newFd, F_SETFL, oldFlags & O_NONBLOCK) != 0) {
|
||||
close(newFd);
|
||||
return -errno;
|
||||
}
|
||||
if (dup2(newFd, aFd) < 0) {
|
||||
close(newFd);
|
||||
return -errno;
|
||||
}
|
||||
close(newFd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static intptr_t ConnectTrap(ArgsRef aArgs, void* aux) {
|
||||
typedef const struct sockaddr_un* AddrPtr;
|
||||
|
||||
return ConnectTrapCommon(static_cast<SandboxBrokerClient*>(aux),
|
||||
static_cast<int>(aArgs.args[0]),
|
||||
reinterpret_cast<AddrPtr>(aArgs.args[1]),
|
||||
static_cast<socklen_t>(aArgs.args[2]));
|
||||
}
|
||||
|
||||
static intptr_t ConnectTrapLegacy(ArgsRef aArgs, void* aux) {
|
||||
const auto innerArgs = reinterpret_cast<unsigned long*>(aArgs.args[1]);
|
||||
typedef const struct sockaddr_un* AddrPtr;
|
||||
|
||||
return ConnectTrapCommon(static_cast<SandboxBrokerClient*>(aux),
|
||||
static_cast<int>(innerArgs[0]),
|
||||
reinterpret_cast<AddrPtr>(innerArgs[1]),
|
||||
static_cast<socklen_t>(innerArgs[2]));
|
||||
}
|
||||
|
||||
public:
|
||||
ContentSandboxPolicy(SandboxBrokerClient* aBroker,
|
||||
ContentProcessSandboxParams&& aParams)
|
||||
: mParams(std::move(aParams)),
|
||||
: SandboxPolicyCommon(aBroker, ShmemUsage::MAY_CREATE,
|
||||
AllowUnsafeSocketPair::YES),
|
||||
mParams(std::move(aParams)),
|
||||
mAllowSysV(PR_GetEnv("MOZ_SANDBOX_ALLOW_SYSV") != nullptr),
|
||||
mUsingRenderDoc(PR_GetEnv("RENDERDOC_CAPTUREOPTS") != nullptr) {
|
||||
mBroker = aBroker;
|
||||
mMayCreateShmem = true;
|
||||
mAllowUnsafeSocketPair = true;
|
||||
mBrokeredConnect = true;
|
||||
}
|
||||
mUsingRenderDoc(PR_GetEnv("RENDERDOC_CAPTUREOPTS") != nullptr) {}
|
||||
|
||||
~ContentSandboxPolicy() override = default;
|
||||
|
||||
Maybe<ResultExpr> EvaluateSocketCall(int aCall,
|
||||
bool aHasArgs) const override {
|
||||
switch (aCall) {
|
||||
case SYS_RECVFROM:
|
||||
case SYS_SENDTO:
|
||||
case SYS_SENDMMSG: // libresolv via libasyncns; see bug 1355274
|
||||
return Some(Allow());
|
||||
|
||||
|
@ -1270,23 +1248,22 @@ class ContentSandboxPolicy : public SandboxPolicyCommon {
|
|||
case SYS_SOCKET:
|
||||
return Some(Error(EACCES));
|
||||
#else // #ifdef DESKTOP
|
||||
case SYS_SOCKET:
|
||||
case SYS_CONNECT:
|
||||
if (BelowLevel(4)) {
|
||||
return Some(Allow());
|
||||
}
|
||||
return SandboxPolicyCommon::EvaluateSocketCall(aCall, aHasArgs);
|
||||
|
||||
// FIXME (bug 1761134): sockopts should be filtered
|
||||
case SYS_SOCKET: {
|
||||
const auto trapFn = aHasArgs ? FakeSocketTrap : FakeSocketTrapLegacy;
|
||||
return Some(AllowBelowLevel(4, Trap(trapFn, nullptr)));
|
||||
}
|
||||
case SYS_CONNECT: {
|
||||
const auto trapFn = aHasArgs ? ConnectTrap : ConnectTrapLegacy;
|
||||
return Some(AllowBelowLevel(4, Trap(trapFn, mBroker)));
|
||||
}
|
||||
case SYS_RECV:
|
||||
case SYS_SEND:
|
||||
case SYS_GETSOCKOPT:
|
||||
case SYS_SETSOCKOPT:
|
||||
// These next 3 were needed for X11; they may not be needed
|
||||
// with X11 lockdown, but there's not much attack surface here.
|
||||
case SYS_GETSOCKNAME:
|
||||
case SYS_GETPEERNAME:
|
||||
case SYS_SHUTDOWN:
|
||||
return Some(Allow());
|
||||
|
||||
case SYS_ACCEPT:
|
||||
case SYS_ACCEPT4:
|
||||
if (mUsingRenderDoc) {
|
||||
|
@ -1497,6 +1474,9 @@ class ContentSandboxPolicy : public SandboxPolicyCommon {
|
|||
case __NR_times:
|
||||
return Allow();
|
||||
|
||||
CASES_FOR_dup2: // See ConnectTrapCommon
|
||||
return Allow();
|
||||
|
||||
case __NR_fsync:
|
||||
case __NR_msync:
|
||||
return Allow();
|
||||
|
@ -1782,11 +1762,9 @@ UniquePtr<sandbox::bpf_dsl::Policy> GetMediaSandboxPolicy(
|
|||
// segments, so it may need file brokering.
|
||||
class RDDSandboxPolicy final : public SandboxPolicyCommon {
|
||||
public:
|
||||
explicit RDDSandboxPolicy(SandboxBrokerClient* aBroker) {
|
||||
mBroker = aBroker;
|
||||
mMayCreateShmem = true;
|
||||
mBrokeredConnect = true;
|
||||
}
|
||||
explicit RDDSandboxPolicy(SandboxBrokerClient* aBroker)
|
||||
: SandboxPolicyCommon(aBroker, ShmemUsage::MAY_CREATE,
|
||||
AllowUnsafeSocketPair::NO) {}
|
||||
|
||||
#ifndef ANDROID
|
||||
Maybe<ResultExpr> EvaluateIpcCall(int aCall, int aArgShift) const override {
|
||||
|
@ -1821,11 +1799,11 @@ class RDDSandboxPolicy final : public SandboxPolicyCommon {
|
|||
Maybe<ResultExpr> EvaluateSocketCall(int aCall,
|
||||
bool aHasArgs) const override {
|
||||
switch (aCall) {
|
||||
// These are for X11.
|
||||
case SYS_GETSOCKNAME:
|
||||
case SYS_GETPEERNAME:
|
||||
case SYS_SHUTDOWN:
|
||||
return Some(Allow());
|
||||
// Mesa can call getpwuid_r to get the home dir, which can try
|
||||
// to connect to nscd (or maybe servers like NIS or LDAP); this
|
||||
// can't be safely allowed, but we can quietly deny it.
|
||||
case SYS_SOCKET:
|
||||
return Some(Error(EACCES));
|
||||
|
||||
default:
|
||||
return SandboxPolicyCommon::EvaluateSocketCall(aCall, aHasArgs);
|
||||
|
@ -1897,10 +1875,9 @@ UniquePtr<sandbox::bpf_dsl::Policy> GetDecoderSandboxPolicy(
|
|||
// the SocketProcess sandbox looks like.
|
||||
class SocketProcessSandboxPolicy final : public SandboxPolicyCommon {
|
||||
public:
|
||||
explicit SocketProcessSandboxPolicy(SandboxBrokerClient* aBroker) {
|
||||
mBroker = aBroker;
|
||||
mMayCreateShmem = true;
|
||||
}
|
||||
explicit SocketProcessSandboxPolicy(SandboxBrokerClient* aBroker)
|
||||
: SandboxPolicyCommon(aBroker, ShmemUsage::MAY_CREATE,
|
||||
AllowUnsafeSocketPair::NO) {}
|
||||
|
||||
static intptr_t FcntlTrap(const sandbox::arch_seccomp_data& aArgs,
|
||||
void* aux) {
|
||||
|
@ -1920,15 +1897,22 @@ class SocketProcessSandboxPolicy final : public SandboxPolicyCommon {
|
|||
Maybe<ResultExpr> EvaluateSocketCall(int aCall,
|
||||
bool aHasArgs) const override {
|
||||
switch (aCall) {
|
||||
case SYS_SOCKET:
|
||||
case SYS_CONNECT:
|
||||
case SYS_BIND:
|
||||
return Some(Allow());
|
||||
|
||||
// FIXME(bug 1641401) do we really need this?
|
||||
case SYS_SOCKET:
|
||||
return Some(Allow());
|
||||
|
||||
case SYS_CONNECT:
|
||||
return Some(Allow());
|
||||
|
||||
case SYS_RECVFROM:
|
||||
case SYS_SENDTO:
|
||||
case SYS_SENDMMSG:
|
||||
return Some(Allow());
|
||||
|
||||
case SYS_RECV:
|
||||
case SYS_SEND:
|
||||
case SYS_GETSOCKOPT:
|
||||
case SYS_SETSOCKOPT:
|
||||
case SYS_GETSOCKNAME:
|
||||
|
@ -2029,10 +2013,9 @@ UniquePtr<sandbox::bpf_dsl::Policy> GetSocketProcessSandboxPolicy(
|
|||
|
||||
class UtilitySandboxPolicy : public SandboxPolicyCommon {
|
||||
public:
|
||||
explicit UtilitySandboxPolicy(SandboxBrokerClient* aBroker) {
|
||||
mBroker = aBroker;
|
||||
mMayCreateShmem = true;
|
||||
}
|
||||
explicit UtilitySandboxPolicy(SandboxBrokerClient* aBroker)
|
||||
: SandboxPolicyCommon(aBroker, ShmemUsage::MAY_CREATE,
|
||||
AllowUnsafeSocketPair::NO) {}
|
||||
|
||||
ResultExpr PrctlPolicy() const override {
|
||||
Arg<int> op(0);
|
||||
|
|
|
@ -327,64 +327,6 @@ static void AddDynamicPathList(SandboxBroker::Policy* policy,
|
|||
}
|
||||
}
|
||||
|
||||
static void AddX11Dependencies(SandboxBroker::Policy* policy) {
|
||||
// Allow Primus to contact the Bumblebee daemon to manage GPU
|
||||
// switching on NVIDIA Optimus systems.
|
||||
const char* bumblebeeSocket = PR_GetEnv("BUMBLEBEE_SOCKET");
|
||||
if (bumblebeeSocket == nullptr) {
|
||||
bumblebeeSocket = "/var/run/bumblebee.socket";
|
||||
}
|
||||
policy->AddPath(SandboxBroker::MAY_CONNECT, bumblebeeSocket);
|
||||
|
||||
#if defined(MOZ_WIDGET_GTK) && defined(MOZ_X11)
|
||||
// Allow local X11 connections, for several purposes:
|
||||
//
|
||||
// * for content processes to use WebGL when the browser is in headless
|
||||
// mode, by opening the X display if/when needed
|
||||
//
|
||||
// * if Primus or VirtualGL is used, to contact the secondary X server
|
||||
static const bool kIsX11 =
|
||||
!mozilla::widget::GdkIsWaylandDisplay() && PR_GetEnv("DISPLAY");
|
||||
if (kIsX11) {
|
||||
policy->AddPrefix(SandboxBroker::MAY_CONNECT, "/tmp/.X11-unix/X");
|
||||
if (auto* const xauth = PR_GetEnv("XAUTHORITY")) {
|
||||
policy->AddPath(rdonly, xauth);
|
||||
} else if (auto* const home = PR_GetEnv("HOME")) {
|
||||
// This follows the logic in libXau: append "/.Xauthority",
|
||||
// even if $HOME ends in a slash, except in the special case
|
||||
// where HOME=/ because POSIX allows implementations to treat
|
||||
// an initial double slash specially.
|
||||
nsAutoCString xauth(home);
|
||||
if (xauth != "/"_ns) {
|
||||
xauth.Append('/');
|
||||
}
|
||||
xauth.AppendLiteral(".Xauthority");
|
||||
policy->AddPath(rdonly, xauth.get());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void AddGLDependencies(SandboxBroker::Policy* policy) {
|
||||
// Devices
|
||||
policy->AddDir(rdwr, "/dev/dri");
|
||||
policy->AddFilePrefix(rdwr, "/dev", "nvidia");
|
||||
|
||||
// Hardware info
|
||||
AddDriPaths(policy);
|
||||
|
||||
// /etc and /usr/share (glvnd, libdrm, drirc, ...?)
|
||||
policy->AddDir(rdonly, "/etc");
|
||||
policy->AddDir(rdonly, "/usr/share");
|
||||
policy->AddDir(rdonly, "/usr/local/share");
|
||||
|
||||
// Note: This function doesn't do anything about Mesa's shader
|
||||
// cache, because the details can vary by process type, including
|
||||
// whether caching is enabled.
|
||||
|
||||
AddX11Dependencies(policy);
|
||||
}
|
||||
|
||||
void SandboxBrokerPolicyFactory::InitContentPolicy() {
|
||||
const bool headless =
|
||||
StaticPrefs::security_sandbox_content_headless_AtStartup();
|
||||
|
@ -393,14 +335,18 @@ void SandboxBrokerPolicyFactory::InitContentPolicy() {
|
|||
// are cached over the lifetime of the factory.
|
||||
SandboxBroker::Policy* policy = new SandboxBroker::Policy;
|
||||
// Write permssions
|
||||
//
|
||||
if (!headless) {
|
||||
// Bug 1308851: NVIDIA proprietary driver when using WebGL
|
||||
policy->AddFilePrefix(rdwr, "/dev", "nvidia");
|
||||
|
||||
// Bug 1312678: Mesa with DRI when using WebGL
|
||||
policy->AddDir(rdwr, "/dev/dri");
|
||||
}
|
||||
|
||||
// Bug 1575985: WASM library sandbox needs RW access to /dev/null
|
||||
policy->AddPath(rdwr, "/dev/null");
|
||||
|
||||
if (!headless) {
|
||||
AddGLDependencies(policy);
|
||||
}
|
||||
|
||||
// Read permissions
|
||||
policy->AddPath(rdonly, "/dev/urandom");
|
||||
policy->AddPath(rdonly, "/dev/random");
|
||||
|
@ -426,6 +372,9 @@ void SandboxBrokerPolicyFactory::InitContentPolicy() {
|
|||
policy->AddDir(rdonly, "/run/host/local-fonts");
|
||||
policy->AddDir(rdonly, "/var/cache/fontconfig");
|
||||
|
||||
if (!headless) {
|
||||
AddDriPaths(policy);
|
||||
}
|
||||
AddLdconfigPaths(policy);
|
||||
AddLdLibraryEnvPaths(policy);
|
||||
|
||||
|
@ -622,7 +571,41 @@ void SandboxBrokerPolicyFactory::InitContentPolicy() {
|
|||
#endif
|
||||
|
||||
if (!headless) {
|
||||
AddX11Dependencies(policy);
|
||||
// Allow Primus to contact the Bumblebee daemon to manage GPU
|
||||
// switching on NVIDIA Optimus systems.
|
||||
const char* bumblebeeSocket = PR_GetEnv("BUMBLEBEE_SOCKET");
|
||||
if (bumblebeeSocket == nullptr) {
|
||||
bumblebeeSocket = "/var/run/bumblebee.socket";
|
||||
}
|
||||
policy->AddPath(SandboxBroker::MAY_CONNECT, bumblebeeSocket);
|
||||
|
||||
#if defined(MOZ_WIDGET_GTK) && defined(MOZ_X11)
|
||||
// Allow local X11 connections, for several purposes:
|
||||
//
|
||||
// * for content processes to use WebGL when the browser is in headless
|
||||
// mode, by opening the X display if/when needed
|
||||
//
|
||||
// * if Primus or VirtualGL is used, to contact the secondary X server
|
||||
static const bool kIsX11 =
|
||||
!mozilla::widget::GdkIsWaylandDisplay() && PR_GetEnv("DISPLAY");
|
||||
if (kIsX11) {
|
||||
policy->AddPrefix(SandboxBroker::MAY_CONNECT, "/tmp/.X11-unix/X");
|
||||
if (auto* const xauth = PR_GetEnv("XAUTHORITY")) {
|
||||
policy->AddPath(rdonly, xauth);
|
||||
} else if (auto* const home = PR_GetEnv("HOME")) {
|
||||
// This follows the logic in libXau: append "/.Xauthority",
|
||||
// even if $HOME ends in a slash, except in the special case
|
||||
// where HOME=/ because POSIX allows implementations to treat
|
||||
// an initial double slash specially.
|
||||
nsAutoCString xauth(home);
|
||||
if (xauth != "/"_ns) {
|
||||
xauth.Append('/');
|
||||
}
|
||||
xauth.AppendLiteral(".Xauthority");
|
||||
policy->AddPath(rdonly, xauth.get());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Bug 1732580: when packaged as a strictly confined snap, may need
|
||||
|
@ -855,8 +838,9 @@ SandboxBrokerPolicyFactory::GetRDDPolicy(int aPid) {
|
|||
}
|
||||
}
|
||||
|
||||
// VA-API needs GPU access and GL context creation
|
||||
AddGLDependencies(policy.get());
|
||||
// VA-API needs DRI and GPU detection
|
||||
policy->AddDir(rdwr, "/dev/dri");
|
||||
AddDriPaths(policy.get());
|
||||
|
||||
// FFmpeg and GPU drivers may need general-case library loading
|
||||
AddLdconfigPaths(policy.get());
|
||||
|
|
Загрузка…
Ссылка в новой задаче