From fc1bf47cd86638b08e03b90b60b0bc80dd1d6c28 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Thu, 9 Jun 2022 11:14:27 +0200 Subject: Updated to 101.0.1, More VA-API sandbox fixes (mzbz#1769182) --- .gitignore | 2 + D146271.diff | 94 +++++++++++++ D146272.diff | 373 ++++++++++++++++++++++++++++++++++++++++++++++++++ D146273.diff | 90 ++++++++++++ D146274.diff | 158 +++++++++++++++++++++ D146275.diff | 125 +++++++++++++++++ firefox.spec | 20 ++- mozilla-1773336.patch | 12 ++ sources | 4 +- 9 files changed, 874 insertions(+), 4 deletions(-) create mode 100644 D146271.diff create mode 100644 D146272.diff create mode 100644 D146273.diff create mode 100644 D146274.diff create mode 100644 D146275.diff create mode 100644 mozilla-1773336.patch diff --git a/.gitignore b/.gitignore index 9cb84f4..4ba9226 100644 --- a/.gitignore +++ b/.gitignore @@ -513,3 +513,5 @@ firefox-3.6.4.source.tar.bz2 /firefox-langpacks-100.0.2-20220520.tar.xz /firefox-101.0.source.tar.xz /firefox-langpacks-101.0-20220530.tar.xz +/firefox-101.0.1.source.tar.xz +/firefox-langpacks-101.0.1-20220609.tar.xz diff --git a/D146271.diff b/D146271.diff new file mode 100644 index 0000000..fd2e0b0 --- /dev/null +++ b/D146271.diff @@ -0,0 +1,94 @@ +diff -up firefox-101.0/security/sandbox/linux/SandboxFilter.cpp.D146271.diff firefox-101.0/security/sandbox/linux/SandboxFilter.cpp +--- firefox-101.0/security/sandbox/linux/SandboxFilter.cpp.D146271.diff 2022-05-27 01:16:59.000000000 +0200 ++++ firefox-101.0/security/sandbox/linux/SandboxFilter.cpp 2022-06-09 09:59:35.569235176 +0200 +@@ -125,28 +125,12 @@ namespace mozilla { + // denied if no broker client is provided by the concrete class. + class SandboxPolicyCommon : public SandboxPolicyBase { + protected: +- enum class ShmemUsage : uint8_t { +- MAY_CREATE, +- ONLY_USE, +- }; +- +- enum class AllowUnsafeSocketPair : uint8_t { +- NO, +- YES, +- }; +- ++ // Subclasses can assign these in their constructors to loosen the ++ // default settings. + SandboxBrokerClient* mBroker = nullptr; + bool mMayCreateShmem = false; + bool mAllowUnsafeSocketPair = false; + +- explicit SandboxPolicyCommon(SandboxBrokerClient* aBroker, +- ShmemUsage aShmemUsage, +- AllowUnsafeSocketPair aAllowUnsafeSocketPair) +- : mBroker(aBroker), +- mMayCreateShmem(aShmemUsage == ShmemUsage::MAY_CREATE), +- mAllowUnsafeSocketPair(aAllowUnsafeSocketPair == +- AllowUnsafeSocketPair::YES) {} +- + SandboxPolicyCommon() = default; + + typedef const sandbox::arch_seccomp_data& ArgsRef; +@@ -1228,11 +1212,13 @@ class ContentSandboxPolicy : public Sand + public: + ContentSandboxPolicy(SandboxBrokerClient* aBroker, + ContentProcessSandboxParams&& aParams) +- : SandboxPolicyCommon(aBroker, ShmemUsage::MAY_CREATE, +- AllowUnsafeSocketPair::YES), +- mParams(std::move(aParams)), ++ : mParams(std::move(aParams)), + mAllowSysV(PR_GetEnv("MOZ_SANDBOX_ALLOW_SYSV") != nullptr), +- mUsingRenderDoc(PR_GetEnv("RENDERDOC_CAPTUREOPTS") != nullptr) {} ++ mUsingRenderDoc(PR_GetEnv("RENDERDOC_CAPTUREOPTS") != nullptr) { ++ mBroker = aBroker; ++ mMayCreateShmem = true; ++ mAllowUnsafeSocketPair = true; ++ } + + ~ContentSandboxPolicy() override = default; + +@@ -1762,9 +1748,10 @@ UniquePtr GetM + // segments, so it may need file brokering. + class RDDSandboxPolicy final : public SandboxPolicyCommon { + public: +- explicit RDDSandboxPolicy(SandboxBrokerClient* aBroker) +- : SandboxPolicyCommon(aBroker, ShmemUsage::MAY_CREATE, +- AllowUnsafeSocketPair::NO) {} ++ explicit RDDSandboxPolicy(SandboxBrokerClient* aBroker) { ++ mBroker = aBroker; ++ mMayCreateShmem = true; ++ } + + #ifndef ANDROID + Maybe EvaluateIpcCall(int aCall, int aArgShift) const override { +@@ -1875,9 +1862,10 @@ UniquePtr GetD + // the SocketProcess sandbox looks like. + class SocketProcessSandboxPolicy final : public SandboxPolicyCommon { + public: +- explicit SocketProcessSandboxPolicy(SandboxBrokerClient* aBroker) +- : SandboxPolicyCommon(aBroker, ShmemUsage::MAY_CREATE, +- AllowUnsafeSocketPair::NO) {} ++ explicit SocketProcessSandboxPolicy(SandboxBrokerClient* aBroker) { ++ mBroker = aBroker; ++ mMayCreateShmem = true; ++ } + + static intptr_t FcntlTrap(const sandbox::arch_seccomp_data& aArgs, + void* aux) { +@@ -2013,9 +2001,10 @@ UniquePtr GetS + + class UtilitySandboxPolicy : public SandboxPolicyCommon { + public: +- explicit UtilitySandboxPolicy(SandboxBrokerClient* aBroker) +- : SandboxPolicyCommon(aBroker, ShmemUsage::MAY_CREATE, +- AllowUnsafeSocketPair::NO) {} ++ explicit UtilitySandboxPolicy(SandboxBrokerClient* aBroker) { ++ mBroker = aBroker; ++ mMayCreateShmem = true; ++ } + + ResultExpr PrctlPolicy() const override { + Arg op(0); diff --git a/D146272.diff b/D146272.diff new file mode 100644 index 0000000..0a2c749 --- /dev/null +++ b/D146272.diff @@ -0,0 +1,373 @@ +diff --git a/security/sandbox/linux/SandboxFilter.cpp b/security/sandbox/linux/SandboxFilter.cpp +--- a/security/sandbox/linux/SandboxFilter.cpp ++++ b/security/sandbox/linux/SandboxFilter.cpp +@@ -128,10 +128,11 @@ + // Subclasses can assign these in their constructors to loosen the + // default settings. + SandboxBrokerClient* mBroker = nullptr; + bool mMayCreateShmem = false; + bool mAllowUnsafeSocketPair = false; ++ bool mBrokeredConnect = false; // Can connect() be brokered? + + SandboxPolicyCommon() = default; + + typedef const sandbox::arch_seccomp_data& ArgsRef; + +@@ -533,10 +534,124 @@ + MOZ_CRASH("unreachable?"); + return -ENOSYS; + #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(aArgs.args[0]), ++ static_cast(aArgs.args[1]), ++ static_cast(aArgs.args[2])); ++ } ++ ++ static intptr_t FakeSocketTrapLegacy(ArgsRef aArgs, void* aux) { ++ const auto innerArgs = reinterpret_cast(aArgs.args[1]); ++ ++ return FakeSocketTrapCommon(static_cast(innerArgs[0]), ++ static_cast(innerArgs[1]), ++ static_cast(innerArgs[2])); ++ } ++ ++ static Maybe 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(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(aux), ++ static_cast(aArgs.args[0]), ++ reinterpret_cast(aArgs.args[1]), ++ static_cast(aArgs.args[2])); ++ } ++ ++ static intptr_t ConnectTrapLegacy(ArgsRef aArgs, void* aux) { ++ const auto innerArgs = reinterpret_cast(aArgs.args[1]); ++ typedef const struct sockaddr_un* AddrPtr; ++ ++ return ConnectTrapCommon(static_cast(aux), ++ static_cast(innerArgs[0]), ++ reinterpret_cast(innerArgs[1]), ++ static_cast(innerArgs[2])); ++ } ++ + public: + ResultExpr InvalidSyscall() const override { + return Trap(BlockedSyscallTrap, nullptr); + } + +@@ -630,15 +745,37 @@ + return Some(Allow()); + } + Arg level(1), optname(2); + // SO_SNDBUF is used by IPC to avoid constructing + // unnecessarily large gather arrays for `sendmsg`. +- return Some( +- If(AllOf(level == SOL_SOCKET, optname == SO_SNDBUF), Allow()) +- .Else(InvalidSyscall())); ++ // ++ // 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())); + } + ++ // 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(); + } + } + +@@ -1006,10 +1143,16 @@ + return If(AnyOf(request == TCGETS, request == TIOCGWINSZ), + Error(ENOTTY)) + .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: { + Arg fd(0); + return If(fd == STDERR_FILENO, Error(ENOTTY)).Else(InvalidSyscall()); +@@ -1093,133 +1236,20 @@ + + close(fd); + 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(aArgs.args[0]), +- static_cast(aArgs.args[1]), +- static_cast(aArgs.args[2])); +- } +- +- static intptr_t FakeSocketTrapLegacy(ArgsRef aArgs, void* aux) { +- const auto innerArgs = reinterpret_cast(aArgs.args[1]); +- +- return FakeSocketTrapCommon(static_cast(innerArgs[0]), +- static_cast(innerArgs[1]), +- static_cast(innerArgs[2])); +- } +- +- static Maybe 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(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(aux), +- static_cast(aArgs.args[0]), +- reinterpret_cast(aArgs.args[1]), +- static_cast(aArgs.args[2])); +- } +- +- static intptr_t ConnectTrapLegacy(ArgsRef aArgs, void* aux) { +- const auto innerArgs = reinterpret_cast(aArgs.args[1]); +- typedef const struct sockaddr_un* AddrPtr; +- +- return ConnectTrapCommon(static_cast(aux), +- static_cast(innerArgs[0]), +- reinterpret_cast(innerArgs[1]), +- static_cast(innerArgs[2])); +- } +- + public: + ContentSandboxPolicy(SandboxBrokerClient* aBroker, + ContentProcessSandboxParams&& aParams) + : 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; + } + + ~ContentSandboxPolicy() override = default; + + Maybe EvaluateSocketCall(int aCall, +@@ -1232,18 +1262,16 @@ + + #ifdef ANDROID + case SYS_SOCKET: + return Some(Error(EACCES)); + #else // #ifdef DESKTOP +- 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_SOCKET: ++ case SYS_CONNECT: ++ if (BelowLevel(4)) { ++ return Some(Allow()); ++ } ++ return SandboxPolicyCommon::EvaluateSocketCall(aCall, aHasArgs); + case SYS_RECV: + case SYS_SEND: + case SYS_GETSOCKOPT: + case SYS_SETSOCKOPT: + case SYS_GETSOCKNAME: +@@ -1458,13 +1486,10 @@ + + case __NR_getrusage: + case __NR_times: + return Allow(); + +- CASES_FOR_dup2: // See ConnectTrapCommon +- return Allow(); +- + case __NR_fsync: + case __NR_msync: + return Allow(); + + case __NR_getpriority: + diff --git a/D146273.diff b/D146273.diff new file mode 100644 index 0000000..0d838e2 --- /dev/null +++ b/D146273.diff @@ -0,0 +1,90 @@ +diff --git a/security/sandbox/linux/SandboxFilter.cpp b/security/sandbox/linux/SandboxFilter.cpp +--- a/security/sandbox/linux/SandboxFilter.cpp ++++ b/security/sandbox/linux/SandboxFilter.cpp +@@ -699,10 +699,18 @@ + Maybe EvaluateSocketCall(int aCall, + bool aHasArgs) const override { + 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: { + // We try to allow "safe" (always connected) socketpairs when using the + // file broker, or for content processes, but we may need to fall back +@@ -1253,12 +1261,10 @@ + ~ContentSandboxPolicy() override = default; + + Maybe 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()); + + #ifdef ANDROID + case SYS_SOCKET: +@@ -1268,18 +1274,21 @@ + case SYS_CONNECT: + if (BelowLevel(4)) { + return Some(Allow()); + } + return SandboxPolicyCommon::EvaluateSocketCall(aCall, aHasArgs); +- case SYS_RECV: +- case SYS_SEND: ++ ++ // FIXME (bug 1761134): sockopts should be filtered + 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) { + return Some(Allow()); + } +@@ -1908,26 +1917,19 @@ + } + + Maybe EvaluateSocketCall(int aCall, + bool aHasArgs) const override { + switch (aCall) { ++ case SYS_SOCKET: ++ case SYS_CONNECT: + case SYS_BIND: + return Some(Allow()); + +- case SYS_SOCKET: +- return Some(Allow()); +- +- case SYS_CONNECT: +- return Some(Allow()); +- +- case SYS_RECVFROM: +- case SYS_SENDTO: ++ // FIXME(bug 1641401) do we really need this? + case SYS_SENDMMSG: + return Some(Allow()); + +- case SYS_RECV: +- case SYS_SEND: + case SYS_GETSOCKOPT: + case SYS_SETSOCKOPT: + case SYS_GETSOCKNAME: + case SYS_GETPEERNAME: + case SYS_SHUTDOWN: + diff --git a/D146274.diff b/D146274.diff new file mode 100644 index 0000000..8943ac4 --- /dev/null +++ b/D146274.diff @@ -0,0 +1,158 @@ +diff --git a/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp b/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp +--- a/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp ++++ b/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp +@@ -325,30 +325,84 @@ + policy->AddDynamic(perms, trimPath.get()); + } + } + } + ++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(); + + // Policy entries that are the same in every process go here, and + // 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"); + policy->AddPath(rdonly, "/proc/sys/crypto/fips_enabled"); + policy->AddPath(rdonly, "/proc/cpuinfo"); +@@ -370,13 +424,10 @@ + policy->AddDir(rdonly, "/run/host/fonts"); + policy->AddDir(rdonly, "/run/host/user-fonts"); + policy->AddDir(rdonly, "/run/host/local-fonts"); + policy->AddDir(rdonly, "/var/cache/fontconfig"); + +- if (!headless) { +- AddDriPaths(policy); +- } + AddLdconfigPaths(policy); + AddLdLibraryEnvPaths(policy); + + if (!headless) { + // Bug 1385715: NVIDIA PRIME support +@@ -569,45 +620,11 @@ + } + } + #endif + + if (!headless) { +- // 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 ++ AddX11Dependencies(policy); + } + + // Bug 1732580: when packaged as a strictly confined snap, may need + // read-access to configuration files under $SNAP/. + const char* snap = PR_GetEnv("SNAP"); + diff --git a/D146275.diff b/D146275.diff new file mode 100644 index 0000000..989b317 --- /dev/null +++ b/D146275.diff @@ -0,0 +1,125 @@ +diff --git a/ipc/glue/GeckoChildProcessHost.cpp b/ipc/glue/GeckoChildProcessHost.cpp +--- a/ipc/glue/GeckoChildProcessHost.cpp ++++ b/ipc/glue/GeckoChildProcessHost.cpp +@@ -418,10 +418,17 @@ + nsresult rv = NS_GetSpecialDirectory(NS_APP_CONTENT_PROCESS_TEMP_DIR, + getter_AddRefs(contentTempDir)); + 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) + if (aProcessType == GeckoProcessType_Content && ForkServiceChild::Get()) { + mLaunchOptions->use_forkserver = true; +diff --git a/security/sandbox/common/test/SandboxTestingChildTests.h b/security/sandbox/common/test/SandboxTestingChildTests.h +--- a/security/sandbox/common/test/SandboxTestingChildTests.h ++++ b/security/sandbox/common/test/SandboxTestingChildTests.h +@@ -21,14 +21,16 @@ + # include + # include + # include + # include + # include ++# include + # include + # include + # include + # include "mozilla/ProcInfo_linux.h" ++# include "mozilla/UniquePtrExtensions.h" + # ifdef MOZ_X11 + # include "X11/Xlib.h" + # include "X11UndefineNone.h" + # endif // MOZ_X11 + # endif // XP_LINUX +@@ -595,12 +597,25 @@ + return rv; + }); + + RunTestsSched(child); + +- child->ErrnoTest("socket"_ns, false, +- [] { return socket(AF_UNIX, SOCK_STREAM, 0); }); ++ child->ErrnoTest("socket_inet"_ns, false, ++ [] { return socket(AF_INET, SOCK_STREAM, 0); }); ++ ++ { ++ UniqueFileHandle fd(socket(AF_UNIX, SOCK_STREAM, 0)); ++ child->ErrnoTest("socket_unix"_ns, true, [&] { return fd.get(); }); ++ ++ struct sockaddr_un sun {}; ++ sun.sun_family = AF_UNIX; ++ strncpy(sun.sun_path, "/tmp/forbidden-sock", sizeof(sun.sun_path)); ++ ++ child->ErrnoValueTest("socket_unix_bind"_ns, ENOSYS, [&] { ++ return bind(fd.get(), (struct sockaddr*)&sun, sizeof(sun)); ++ }); ++ } + + child->ErrnoTest("uname"_ns, true, [] { + struct utsname uts; + return uname(&uts); + }); +diff --git a/security/sandbox/linux/SandboxFilter.cpp b/security/sandbox/linux/SandboxFilter.cpp +--- a/security/sandbox/linux/SandboxFilter.cpp ++++ b/security/sandbox/linux/SandboxFilter.cpp +@@ -1783,10 +1783,11 @@ + class RDDSandboxPolicy final : public SandboxPolicyCommon { + public: + explicit RDDSandboxPolicy(SandboxBrokerClient* aBroker) { + mBroker = aBroker; + mMayCreateShmem = true; ++ mBrokeredConnect = true; + } + + #ifndef ANDROID + Maybe EvaluateIpcCall(int aCall, int aArgShift) const override { + // The Intel media driver uses SysV IPC (semaphores and shared +@@ -1818,15 +1819,15 @@ + #endif + + Maybe EvaluateSocketCall(int aCall, + bool aHasArgs) const override { + switch (aCall) { +- // 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)); ++ // These are for X11. ++ case SYS_GETSOCKNAME: ++ case SYS_GETPEERNAME: ++ case SYS_SHUTDOWN: ++ return Some(Allow()); + + default: + return SandboxPolicyCommon::EvaluateSocketCall(aCall, aHasArgs); + } + } +diff --git a/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp b/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp +--- a/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp ++++ b/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp +@@ -853,13 +853,12 @@ + if (developer_repo_dir) { + policy->AddDir(rdonly, developer_repo_dir); + } + } + +- // VA-API needs DRI and GPU detection +- policy->AddDir(rdwr, "/dev/dri"); +- AddDriPaths(policy.get()); ++ // VA-API needs GPU access and GL context creation ++ AddGLDependencies(policy.get()); + + // FFmpeg and GPU drivers may need general-case library loading + AddLdconfigPaths(policy.get()); + AddLdLibraryEnvPaths(policy.get()); + + diff --git a/firefox.spec b/firefox.spec index 4d49292..118e3ca 100644 --- a/firefox.spec +++ b/firefox.spec @@ -162,8 +162,8 @@ ExcludeArch: aarch64 Summary: Mozilla Firefox Web browser Name: firefox -Version: 101.0 -Release: 2%{?pre_tag}%{?dist} +Version: 101.0.1 +Release: 1%{?pre_tag}%{?dist} URL: https://www.mozilla.org/firefox/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: https://archive.mozilla.org/pub/firefox/releases/%{version}%{?pre_version}/source/firefox-%{version}%{?pre_version}.source.tar.xz @@ -219,6 +219,7 @@ Patch62: build-python.patch Patch71: 0001-GLIBCXX-fix-for-GCC-12.patch Patch73: D147266.diff Patch74: D147267.diff +Patch75: mozilla-1773336.patch # Test patches # Generate without context by @@ -256,6 +257,11 @@ Patch427: D146087.diff Patch428: D145725.diff Patch429: D145966.diff Patch430: D145871.diff +Patch431: D146271.diff +Patch432: D146272.diff +Patch433: D146273.diff +Patch434: D146274.diff +Patch435: D146275.diff # NVIDIA mzbz#1735929 Patch440: D147635.diff @@ -480,6 +486,7 @@ This package contains results of tests executed during build. %patch71 -p1 -b .0001-GLIBCXX-fix-for-GCC-12 %patch73 -p1 -b .D147266 %patch74 -p1 -b .D147267 +%patch75 -p1 -b .mzbz#1773336 # Test patches #%patch100 -p1 -b .firefox-tests-xpcshell @@ -514,6 +521,11 @@ This package contains results of tests executed during build. %patch428 -p1 -b .D145725.diff %patch429 -p1 -b .D145966.diff %patch430 -p1 -b .D145871.diff +%patch431 -p1 -b .D146271.diff +%patch432 -p1 -b .D146272.diff +%patch433 -p1 -b .D146273.diff +%patch434 -p1 -b .D146274.diff +%patch435 -p1 -b .D146275.diff # NVIDIA mzbz#1735929 %patch440 -p1 -b .D147635.diff @@ -1095,6 +1107,10 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #--------------------------------------------------------------------- %changelog +* Thu Jun 9 2022 Martin Stransky - 101.0.1-1 +- Updated to 101.0.1 +- More VA-API sandbox fixes (mzbz#1769182) + * Tue Jun 7 2022 Martin Stransky - 101.0-2 - Enabled VA-API by default (+ added VA-API fixes from upstream) - Fixed WebGL performance on NVIDIA drivers (mzbz#1735929) diff --git a/mozilla-1773336.patch b/mozilla-1773336.patch new file mode 100644 index 0000000..b65ff89 --- /dev/null +++ b/mozilla-1773336.patch @@ -0,0 +1,12 @@ +diff -up firefox-101.0.1/gfx/webrender_bindings/webrender_ffi.h.old firefox-101.0.1/gfx/webrender_bindings/webrender_ffi.h +--- firefox-101.0.1/gfx/webrender_bindings/webrender_ffi.h.old 2022-06-09 10:31:16.122495733 +0200 ++++ firefox-101.0.1/gfx/webrender_bindings/webrender_ffi.h 2022-06-09 10:31:22.880724352 +0200 +@@ -72,8 +72,6 @@ struct WrPipelineInfo; + struct WrPipelineIdAndEpoch; + using WrPipelineIdEpochs = nsTArray; + +-const uint64_t ROOT_CLIP_CHAIN = ~0; +- + } // namespace wr + } // namespace mozilla + diff --git a/sources b/sources index 0b97dec..ad76a99 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ SHA512 (mochitest-python.tar.gz) = 18e1aeb475df5fbf1fe3838897d5ac2f3114aa349030713fc2be27af087b1b12f57642621b87bd052f324a7cb7fbae5f36b21502191d85692f62c8cdd69c8bf2 -SHA512 (firefox-101.0.source.tar.xz) = fffe7e0940c1443fcdc5b205677764cb4e04b29f33fcfafb2857d383700584f309806b81fc4989efb56cc12a3cca1ff7d451b647050c43e98777b5c952ed5d56 -SHA512 (firefox-langpacks-101.0-20220530.tar.xz) = aa81113b6aef965aa17921d563759da6c499021b6f471369d998c35802f72e79a107080b4df59ca51dae15ac464176f23bce2fc84942f5852e810d963553b687 SHA512 (cbindgen-vendor.tar.xz) = 2bfec52455f133ede2fb7f7e8bcd358cb547a82cbb01e8cef477fe0700ebdfd9cf647cd93a6c11d3b321e441a142e26793c7a7865dba5c93033250ae78cf6b4b +SHA512 (firefox-101.0.1.source.tar.xz) = 435a7f6013582933e75c41e554a45beda30b5affd7d3ed7d2876026609ba7f17b2c20b507d9d0c9ce2379e335ec09b021257ba30ac55fabf02dca54b03ea70b4 +SHA512 (firefox-langpacks-101.0.1-20220609.tar.xz) = 54c93a0fbded6a42948fd578e5577987186ca04695f9c0648718780d3a491b540187addf1239b13c53e532052888bd2ed76788a06c3a2422a060fb0da303ec58 -- cgit