Fix firefox video tab crash with rust 1.51

This commit is contained in:
lingsheng 2021-07-08 15:18:30 +08:00
parent 0d73a0302f
commit b2c7ec42b8
7 changed files with 415 additions and 1 deletions

View File

@ -0,0 +1,60 @@
# HG changeset patch
# User Jed Davis <jld@mozilla.com>
# Date 1598606638 0
# Node ID a65fc6aca1f2337cb5e8e69f50b539d3c0de95ab
# Parent a6c226548fa02c3ac4681499103cd85217c6de07
Bug 1660901 - Support the fstat-like subset of fstatat in the Linux sandbox policies. r=gcp, a=RyanVM
Differential Revision: https://phabricator.services.mozilla.com/D88499
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
@@ -238,16 +238,22 @@ class SandboxPolicyCommon : public Sandb
}
static intptr_t StatAtTrap(ArgsRef aArgs, void* aux) {
auto broker = static_cast<SandboxBrokerClient*>(aux);
auto fd = static_cast<int>(aArgs.args[0]);
auto path = reinterpret_cast<const char*>(aArgs.args[1]);
auto buf = reinterpret_cast<statstruct*>(aArgs.args[2]);
auto flags = static_cast<int>(aArgs.args[3]);
+
+ if (fd != AT_FDCWD && (flags & AT_EMPTY_PATH) != 0 &&
+ strcmp(path, "") == 0) {
+ return ConvertError(fstatsyscall(fd, buf));
+ }
+
if (fd != AT_FDCWD && path[0] != '/') {
SANDBOX_LOG_ERROR("unsupported fd-relative fstatat(%d, \"%s\", %p, %d)",
fd, path, buf, flags);
return BlockedSyscallTrap(aArgs, nullptr);
}
if ((flags & ~AT_SYMLINK_NOFOLLOW) != 0) {
SANDBOX_LOG_ERROR("unsupported flags %d in fstatat(%d, \"%s\", %p, %d)",
(flags & ~AT_SYMLINK_NOFOLLOW), fd, path, buf, flags);
diff --git a/security/sandbox/linux/broker/SandboxBrokerUtils.h b/security/sandbox/linux/broker/SandboxBrokerUtils.h
--- a/security/sandbox/linux/broker/SandboxBrokerUtils.h
+++ b/security/sandbox/linux/broker/SandboxBrokerUtils.h
@@ -14,17 +14,19 @@
// On 32-bit Linux, stat calls are translated by libc into stat64
// calls. We'll intercept those and handle them in the stat functions
// but must be sure to use the right structure layout.
#if defined(__NR_stat64)
typedef struct stat64 statstruct;
# define statsyscall stat64
# define lstatsyscall lstat64
+# define fstatsyscall fstat64
#elif defined(__NR_stat)
typedef struct stat statstruct;
# define statsyscall stat
# define lstatsyscall lstat
+# define fstatsyscall fstat
#else
# error Missing stat syscall include.
#endif
#endif // mozilla_SandboxBrokerUtils_h

View File

@ -0,0 +1,40 @@
# HG changeset patch
# User Julien Cristau <jcristau@mozilla.com>
# Date 1599423639 0
# Node ID 8ecb82a2f65cf6082d50d1e00453fbeba97633fb
# Parent 0ce38d3c2aa2357df4a8fcc5fd39d3af05fce7e1
Bug 1660901 - ignore AT_NO_AUTOMOUNT in fstatat system call. r=jld, a=RyanVM
Per the manpage "Both stat() and lstat() act as though AT_NO_AUTOMOUNT
was set.", so don't bail if it's set in a call to fstatat.
Differential Revision: https://phabricator.services.mozilla.com/D89121
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
@@ -249,19 +249,20 @@ class SandboxPolicyCommon : public Sandb
return ConvertError(fstatsyscall(fd, buf));
}
if (fd != AT_FDCWD && path[0] != '/') {
SANDBOX_LOG_ERROR("unsupported fd-relative fstatat(%d, \"%s\", %p, %d)",
fd, path, buf, flags);
return BlockedSyscallTrap(aArgs, nullptr);
}
- if ((flags & ~AT_SYMLINK_NOFOLLOW) != 0) {
+ if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT)) != 0) {
SANDBOX_LOG_ERROR("unsupported flags %d in fstatat(%d, \"%s\", %p, %d)",
- (flags & ~AT_SYMLINK_NOFOLLOW), fd, path, buf, flags);
+ (flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT)), fd,
+ path, buf, flags);
return BlockedSyscallTrap(aArgs, nullptr);
}
return (flags & AT_SYMLINK_NOFOLLOW) == 0 ? broker->Stat(path, buf)
: broker->LStat(path, buf);
}
static intptr_t ChmodTrap(ArgsRef aArgs, void* aux) {
auto broker = static_cast<SandboxBrokerClient*>(aux);

View File

@ -0,0 +1,48 @@
# HG changeset patch
# User Jed Davis <jld@mozilla.com>
# Date 1603832709 0
# Node ID 13d5867b039948a79fa80fc2081a17b8089f1ed7
# Parent 0322427df80a91fdeace25c1508105074dc8adad
Bug 1673202 - Call fstat directly in Linux sandbox fstatat interception. r=gcp, a=RyanVM
Sandbox policies handle the case of `fstatat(fd, "", AT_EMPTY_PATH|...)`
by invoking the SIGSYS handler (because seccomp-bpf can't tell if the
string will be empty when the syscall would use it), which makes the
equivalent call to `fstat`.
Unfortunately, recent development versions of glibc implement `fstat` by
calling `fstatat`, which causes unbounded recursion and stack overflow.
(This depends on the headers present at build time; see the bug for more
details.) This patch switches it to use the `fstat` (or `fstat64` on
32-bit) syscall directly.
Differential Revision: https://phabricator.services.mozilla.com/D94798
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
@@ -241,17 +241,21 @@ class SandboxPolicyCommon : public Sandb
auto broker = static_cast<SandboxBrokerClient*>(aux);
auto fd = static_cast<int>(aArgs.args[0]);
auto path = reinterpret_cast<const char*>(aArgs.args[1]);
auto buf = reinterpret_cast<statstruct*>(aArgs.args[2]);
auto flags = static_cast<int>(aArgs.args[3]);
if (fd != AT_FDCWD && (flags & AT_EMPTY_PATH) != 0 &&
strcmp(path, "") == 0) {
- return ConvertError(fstatsyscall(fd, buf));
+#ifdef __NR_fstat64
+ return DoSyscall(__NR_fstat64, fd, buf);
+#else
+ return DoSyscall(__NR_fstat, fd, buf);
+#endif
}
if (fd != AT_FDCWD && path[0] != '/') {
SANDBOX_LOG_ERROR("unsupported fd-relative fstatat(%d, \"%s\", %p, %d)",
fd, path, buf, flags);
return BlockedSyscallTrap(aArgs, nullptr);
}
if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT)) != 0) {

View File

@ -0,0 +1,85 @@
# HG changeset patch
# User Jed Davis <jld@mozilla.com>
# Date 1603993288 0
# Node ID 3962fa9f3084c5bca8458cecdaac664dc431164a
# Parent 4e708898d49e078de5f946d03b0627779b282fd0
Bug 1673770 - Extend the handling of fstatat-as-fstat to sandboxes that don't use a file broker. r=gcp, a=RyanVM
The fix for bug 1660901, to handle the subset of fstatat that is
equivalent to fstat, was incomplete: it was added to the existing
hook for the file broker, so processes that don't use a broker (like
GMP) didn't get the fix. That wasn't a problem when the only use of
that feature was in content processes via GTK, but now that glibc has
reimplemented fstat that way, it's necessary for all processes.
Differential Revision: https://phabricator.services.mozilla.com/D95108
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
@@ -248,16 +248,20 @@ class SandboxPolicyCommon : public Sandb
strcmp(path, "") == 0) {
#ifdef __NR_fstat64
return DoSyscall(__NR_fstat64, fd, buf);
#else
return DoSyscall(__NR_fstat, fd, buf);
#endif
}
+ if (!broker) {
+ return BlockedSyscallTrap(aArgs, nullptr);
+ }
+
if (fd != AT_FDCWD && path[0] != '/') {
SANDBOX_LOG_ERROR("unsupported fd-relative fstatat(%d, \"%s\", %p, %d)",
fd, path, buf, flags);
return BlockedSyscallTrap(aArgs, nullptr);
}
if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT)) != 0) {
SANDBOX_LOG_ERROR("unsupported flags %d in fstatat(%d, \"%s\", %p, %d)",
(flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT)), fd,
@@ -442,17 +446,17 @@ class SandboxPolicyCommon : public Sandb
return Nothing();
}
}
ResultExpr EvaluateSyscall(int sysno) const override {
// If a file broker client was provided, route syscalls to it;
// otherwise, fall through to the main policy, which will deny
// them.
- if (mBroker != nullptr) {
+ if (mBroker) {
switch (sysno) {
case __NR_open:
return Trap(OpenTrap, mBroker);
case __NR_openat:
return Trap(OpenAtTrap, mBroker);
case __NR_access:
return Trap(AccessTrap, mBroker);
case __NR_faccessat:
@@ -481,16 +485,23 @@ class SandboxPolicyCommon : public Sandb
return Trap(RmdirTrap, mBroker);
case __NR_unlink:
return Trap(UnlinkTrap, mBroker);
case __NR_readlink:
return Trap(ReadlinkTrap, mBroker);
case __NR_readlinkat:
return Trap(ReadlinkAtTrap, mBroker);
}
+ } else {
+ // In the absence of a broker we still need to handle the
+ // fstat-equivalent subset of fstatat; see bug 1673770.
+ switch (sysno) {
+ CASES_FOR_fstatat:
+ return Trap(StatAtTrap, nullptr);
+ }
}
switch (sysno) {
// Timekeeping
case __NR_clock_nanosleep:
case __NR_clock_getres:
#ifdef __NR_clock_gettime64
case __NR_clock_gettime64:

View File

@ -0,0 +1,46 @@
# HG changeset patch
# User Emilio Cobos Álvarez <emilio@crisal.io>
# Date 1606915787 -3600
# Node ID 8aa3952dd7208d96648ea171f814c748ec027630
# Parent ff436849850a87dfa3db032e80eaba5e5a3536f4
Bug 1680166 - GCC is smarter than clang, so ignore the warning properly. a=RyanVM
diff --git a/security/sandbox/linux/gtest/TestBroker.cpp b/security/sandbox/linux/gtest/TestBroker.cpp
--- a/security/sandbox/linux/gtest/TestBroker.cpp
+++ b/security/sandbox/linux/gtest/TestBroker.cpp
@@ -212,23 +212,27 @@ TEST_F(SandboxBrokerTest, Access) {
TEST_F(SandboxBrokerTest, Stat) {
statstruct realStat, brokeredStat;
ASSERT_EQ(0, statsyscall("/dev/null", &realStat)) << "Shouldn't ever fail!";
EXPECT_EQ(0, Stat("/dev/null", &brokeredStat));
EXPECT_EQ(realStat.st_ino, brokeredStat.st_ino);
EXPECT_EQ(realStat.st_rdev, brokeredStat.st_rdev);
- // Add some indirection to avoid -Wnonnull warnings.
- [&](const char* aPath) {
- EXPECT_EQ(-1, statsyscall(aPath, &realStat));
- EXPECT_EQ(errno, EFAULT);
+#if defined(__clang__) || defined(__GNUC__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wnonnull"
+#endif
+ EXPECT_EQ(-1, statsyscall(nullptr, &realStat));
+ EXPECT_EQ(errno, EFAULT);
- EXPECT_EQ(-EFAULT, Stat(aPath, &brokeredStat));
- }(nullptr);
+ EXPECT_EQ(-EFAULT, Stat(nullptr, &brokeredStat));
+#if defined(__clang__) || defined(__GNUC__)
+# pragma GCC diagnostic pop
+#endif
EXPECT_EQ(-ENOENT, Stat("/var/empty/qwertyuiop", &brokeredStat));
EXPECT_EQ(-EACCES, Stat("/dev", &brokeredStat));
EXPECT_EQ(0, Stat("/proc/self", &brokeredStat));
EXPECT_TRUE(S_ISDIR(brokeredStat.st_mode));
}

View File

@ -0,0 +1,120 @@
# HG changeset patch
# User Emilio Cobos Álvarez <emilio@crisal.io>
# Date 1606907116 0
# Node ID ff436849850a87dfa3db032e80eaba5e5a3536f4
# Parent f326cd8f9f19a8f3b5edf9d6838fdce5b02d9c64
Bug 1680166 - Return EFAULT when given a null path to stat* calls in the sandbox filter. r=gcp, a=RyanVM
It's a common way to check the existence of system calls. Glibc may fall
back to fstatat when statx is called, passing down the null path.
Since we handle fstatat, let's return -EFAULT the same way the real
fstatat syscall would do.
This is needed for the sandbox not to constantly crash due to this statx
call in rustc:
https://github.com/rust-lang/rust/blob/09c9c9f7da72b774cc445c0f56fc0b9792a49647/library/std/src/sys/unix/fs.rs#L119-L123
Differential Revision: https://phabricator.services.mozilla.com/D98414
diff --git a/security/sandbox/linux/SandboxBrokerClient.cpp b/security/sandbox/linux/SandboxBrokerClient.cpp
--- a/security/sandbox/linux/SandboxBrokerClient.cpp
+++ b/security/sandbox/linux/SandboxBrokerClient.cpp
@@ -154,21 +154,29 @@ int SandboxBrokerClient::Open(const char
}
int SandboxBrokerClient::Access(const char* aPath, int aMode) {
Request req = {SANDBOX_FILE_ACCESS, aMode, 0};
return DoCall(&req, aPath, nullptr, nullptr, false);
}
int SandboxBrokerClient::Stat(const char* aPath, statstruct* aStat) {
+ if (!aPath || !aStat) {
+ return -EFAULT;
+ }
+
Request req = {SANDBOX_FILE_STAT, 0, sizeof(statstruct)};
return DoCall(&req, aPath, nullptr, (void*)aStat, false);
}
int SandboxBrokerClient::LStat(const char* aPath, statstruct* aStat) {
+ if (!aPath || !aStat) {
+ return -EFAULT;
+ }
+
Request req = {SANDBOX_FILE_STAT, O_NOFOLLOW, sizeof(statstruct)};
return DoCall(&req, aPath, nullptr, (void*)aStat, false);
}
int SandboxBrokerClient::Chmod(const char* aPath, int aMode) {
Request req = {SANDBOX_FILE_CHMOD, aMode, 0};
return DoCall(&req, aPath, nullptr, nullptr, false);
}
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
@@ -239,30 +239,30 @@ class SandboxPolicyCommon : public Sandb
static intptr_t StatAtTrap(ArgsRef aArgs, void* aux) {
auto broker = static_cast<SandboxBrokerClient*>(aux);
auto fd = static_cast<int>(aArgs.args[0]);
auto path = reinterpret_cast<const char*>(aArgs.args[1]);
auto buf = reinterpret_cast<statstruct*>(aArgs.args[2]);
auto flags = static_cast<int>(aArgs.args[3]);
- if (fd != AT_FDCWD && (flags & AT_EMPTY_PATH) != 0 &&
- strcmp(path, "") == 0) {
+ if (fd != AT_FDCWD && (flags & AT_EMPTY_PATH) && path &&
+ !strcmp(path, "")) {
#ifdef __NR_fstat64
return DoSyscall(__NR_fstat64, fd, buf);
#else
return DoSyscall(__NR_fstat, fd, buf);
#endif
}
if (!broker) {
return BlockedSyscallTrap(aArgs, nullptr);
}
- if (fd != AT_FDCWD && path[0] != '/') {
+ if (fd != AT_FDCWD && path && path[0] != '/') {
SANDBOX_LOG_ERROR("unsupported fd-relative fstatat(%d, \"%s\", %p, %d)",
fd, path, buf, flags);
return BlockedSyscallTrap(aArgs, nullptr);
}
if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT)) != 0) {
SANDBOX_LOG_ERROR("unsupported flags %d in fstatat(%d, \"%s\", %p, %d)",
(flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT)), fd,
path, buf, flags);
diff --git a/security/sandbox/linux/gtest/TestBroker.cpp b/security/sandbox/linux/gtest/TestBroker.cpp
--- a/security/sandbox/linux/gtest/TestBroker.cpp
+++ b/security/sandbox/linux/gtest/TestBroker.cpp
@@ -212,16 +212,24 @@ TEST_F(SandboxBrokerTest, Access) {
TEST_F(SandboxBrokerTest, Stat) {
statstruct realStat, brokeredStat;
ASSERT_EQ(0, statsyscall("/dev/null", &realStat)) << "Shouldn't ever fail!";
EXPECT_EQ(0, Stat("/dev/null", &brokeredStat));
EXPECT_EQ(realStat.st_ino, brokeredStat.st_ino);
EXPECT_EQ(realStat.st_rdev, brokeredStat.st_rdev);
+ // Add some indirection to avoid -Wnonnull warnings.
+ [&](const char* aPath) {
+ EXPECT_EQ(-1, statsyscall(aPath, &realStat));
+ EXPECT_EQ(errno, EFAULT);
+
+ EXPECT_EQ(-EFAULT, Stat(aPath, &brokeredStat));
+ }(nullptr);
+
EXPECT_EQ(-ENOENT, Stat("/var/empty/qwertyuiop", &brokeredStat));
EXPECT_EQ(-EACCES, Stat("/dev", &brokeredStat));
EXPECT_EQ(0, Stat("/proc/self", &brokeredStat));
EXPECT_TRUE(S_ISDIR(brokeredStat.st_mode));
}
TEST_F(SandboxBrokerTest, LStat) {

View File

@ -88,7 +88,7 @@
Summary: Mozilla Firefox Web browser Summary: Mozilla Firefox Web browser
Name: firefox Name: firefox
Version: 79.0 Version: 79.0
Release: 7 Release: 8
URL: https://www.mozilla.org/firefox/ URL: https://www.mozilla.org/firefox/
License: MPLv1.1 or GPLv2+ or LGPLv2+ License: MPLv1.1 or GPLv2+ or LGPLv2+
Source0: https://archive.mozilla.org/pub/firefox/releases/%{version}/source/firefox-%{version}.source.tar.xz Source0: https://archive.mozilla.org/pub/firefox/releases/%{version}/source/firefox-%{version}.source.tar.xz
@ -177,6 +177,12 @@ Patch632: CVE-2020-26967.patch
Patch633: Fix-build-with-rust-nightly.patch Patch633: Fix-build-with-rust-nightly.patch
Patch634: Teach-style_derives-map_type_params-about-mapping-self-correctly.patch Patch634: Teach-style_derives-map_type_params-about-mapping-self-correctly.patch
Patch635: Update-syn-and-proc-macro2-so-that-Firefox-can-build-on-Rust-nightly-again.patch Patch635: Update-syn-and-proc-macro2-so-that-Firefox-can-build-on-Rust-nightly-again.patch
Patch636: Bug-1660901-Support-the-fstat-like-subset-of-fstatat-in-the-Linux-sandbox-policies.patch
Patch637: Bug-1660901-ignore-AT_NO_AUTOMOUNT-in-fstatat-system-call.patch
Patch638: Bug-1673202-Call-fstat-directly-in-Linux-sandbox-fstatat-interception.patch
Patch639: Bug-1673770-Extend-the-handling-of-fstatat-as-fstat-to-sandboxes-that-dont-use-a-file-broker.patch
Patch640: Bug-1680166-Return-EFAULT-when-given-a-null-path-to-stat-calls-in-the-sandbox-filter.patch
Patch641: Bug-1680166-GCC-is-smarter-than-clang-so-ignore-the-warning-properly.patch
%if %{?system_nss} %if %{?system_nss}
BuildRequires: pkgconfig(nspr) >= %{nspr_version} pkgconfig(nss) >= %{nss_version} BuildRequires: pkgconfig(nspr) >= %{nspr_version} pkgconfig(nss) >= %{nss_version}
@ -347,6 +353,12 @@ tar -xf %{SOURCE3}
%patch633 -p1 %patch633 -p1
%patch634 -p1 %patch634 -p1
%patch635 -p1 %patch635 -p1
%patch636 -p1
%patch637 -p1
%patch638 -p1
%patch639 -p1
%patch640 -p1
%patch641 -p1
%{__rm} -f .mozconfig %{__rm} -f .mozconfig
%{__cp} %{SOURCE10} .mozconfig %{__cp} %{SOURCE10} .mozconfig
echo "ac_add_options --enable-default-toolkit=cairo-gtk3-wayland" >> .mozconfig echo "ac_add_options --enable-default-toolkit=cairo-gtk3-wayland" >> .mozconfig
@ -788,6 +800,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
%endif %endif
%changelog %changelog
* Wed Jul 7 2021 lingsheng <lingsheng@huawei.com> - 79.0-8
- Fix firefox video tab crash with rust 1.51
* Mon Jul 05 2021 caodongxia <caodongxia@huawei.com> - 79.0-7 * Mon Jul 05 2021 caodongxia <caodongxia@huawei.com> - 79.0-7
- Fix build with pipewire 0.3 - Fix build with pipewire 0.3