MFH: r554921 r555014

www/firefox: update to 83.0

Changes:	https://www.mozilla.org/firefox/83.0/releasenotes/
Approved by:	ports-secteam blanket
This commit is contained in:
Jan Beich 2020-11-13 22:51:33 +00:00
parent 5e85f137e1
commit ffdd17519b
Notes: svn2git 2021-03-31 03:12:20 +00:00
svn path=/branches/2020Q4/; revision=555055
6 changed files with 805 additions and 96 deletions

View File

@ -77,8 +77,8 @@ BINARY_ALIAS+= python3=${PYTHON_CMD}
BUNDLE_LIBS= yes
BUILD_DEPENDS+= llvm${LLVM_DEFAULT}>0:devel/llvm${LLVM_DEFAULT} \
rust-cbindgen>=0.14.3:devel/rust-cbindgen \
${RUST_DEFAULT}>=1.41:lang/${RUST_DEFAULT} \
rust-cbindgen>=0.15.0:devel/rust-cbindgen \
${RUST_DEFAULT}>=1.43:lang/${RUST_DEFAULT} \
node:www/node
LIB_DEPENDS+= libdrm.so:graphics/libdrm
MOZ_EXPORT+= ${CONFIGURE_ENV} \

View File

@ -2,18 +2,19 @@
# $FreeBSD$
PORTNAME= firefox
DISTVERSION= 82.0.3
DISTVERSION= 83.0
PORTREVISION= 1
PORTEPOCH= 2
CATEGORIES= www
MASTER_SITES= MOZILLA/${PORTNAME}/releases/${DISTVERSION}/source \
MOZILLA/${PORTNAME}/candidates/${DISTVERSION}-candidates/build1/source
MOZILLA/${PORTNAME}/candidates/${DISTVERSION}-candidates/build2/source
DISTFILES= ${DISTNAME}.source${EXTRACT_SUFX}
MAINTAINER= gecko@FreeBSD.org
COMMENT= Web browser based on the browser portion of Mozilla
BUILD_DEPENDS= nspr>=4.26:devel/nspr \
nss>=3.56:security/nss \
nss>=3.58:security/nss \
icu>=67.1,1:devel/icu \
libevent>=2.1.8:devel/libevent \
harfbuzz>=2.6.8:print/harfbuzz \

View File

@ -1,3 +1,3 @@
TIMESTAMP = 1604872503
SHA256 (firefox-82.0.3.source.tar.xz) = 4df40aecf4b71107c4816db585bcd425f093123f29d8563bc2443a8659058691
SIZE (firefox-82.0.3.source.tar.xz) = 341480104
TIMESTAMP = 1605204503
SHA256 (firefox-83.0.source.tar.xz) = d69e84e8b8449f828683d274c24e03095858362bfed21b08bdd7fe715eea5398
SIZE (firefox-83.0.source.tar.xz) = 351331940

View File

@ -0,0 +1,788 @@
commit cc6e7ab13380
Author: Jed Davis <jld@mozilla.com>
Date: Thu Oct 22 21:23:32 2020 +0000
Bug 1440203 - Support memfd_create in IPC shared memory. r=glandium
This commit also allows `memfd_create` in the seccomp-bpf policy for all
process types.
`memfd_create` is an API added in Linux 3.17 (and adopted by FreeBSD
for the upcoming version 13) for creating anonymous shared memory
not connected to any filesystem. Supporting it means that sandboxed
child processes on Linux can create shared memory directly instead of
messaging a broker, which is unavoidably slower, and it should avoid
the problems we'd been seeing with overly small `/dev/shm` in container
environments (which were causing serious problems for using Firefox for
automated testing of frontend projects).
`memfd_create` also introduces the related operation of file seals:
irrevocably preventing types of modifications to a file. Unfortunately,
the most useful one, `F_SEAL_WRITE`, can't be relied on; see the large
comment in `SharedMemory:ReadOnlyCopy` for details. So we still use
the applicable seals as defense in depth, but read-only copies are
implemented on Linux by using procfs (and see the comments on the
`ReadOnlyCopy` function in `shared_memory_posix.cc` for the subtleties
there).
There's also a FreeBSD implementation, using `cap_rights_limit` for
read-only copies, if the build host is new enough to have the
`memfd_create` function.
The support code for Android, which doesn't support shm_open and can't
use the memfd backend because of issues with its SELinux policy (see bug
1670277), has been reorganized to reflect that we'll always use its own
API, ashmem, in that case.
Differential Revision: https://phabricator.services.mozilla.com/D90605
---
build/moz.configure/headers.configure | 8 +
config/system-headers.mozbuild | 5 +
ipc/chromium/src/base/linux_memfd_defs.h | 69 +++++
ipc/chromium/src/base/shared_memory.h | 3 +-
ipc/chromium/src/base/shared_memory_posix.cc | 428 +++++++++++++++++++++------
ipc/gtest/TestSharedMemory.cpp | 46 +++
security/sandbox/linux/SandboxFilter.cpp | 9 +-
7 files changed, 472 insertions(+), 96 deletions(-)
diff --git build/moz.configure/headers.configure build/moz.configure/headers.configure
index 9445f10a4d53..0f4455d8eeea 100644
--- build/moz.configure/headers.configure
+++ build/moz.configure/headers.configure
@@ -65,6 +65,14 @@ check_headers(
'byteswap.h',
)
+# memfd_create(2) -- Note that older versions of the Linux man-pages
+# project incorrectly cite <sys/memfd.h>, which doesn't exist; this
+# was fixed in the man-pages-5.00 release.
+set_define('HAVE_MEMFD_CREATE',
+ try_compile(includes=['sys/mman.h'],
+ body='memfd_create("", 0);',
+ check_msg='for memfd_create in sys/mman.h'))
+
# TODO: Move these checks to file specific to --enable-project=js.
have_perf_event_h = check_header('linux/perf_event.h',
when=building_linux)
diff --git config/system-headers.mozbuild config/system-headers.mozbuild
index 1dfd3f0a48b8..3c355e3f1d71 100644
--- config/system-headers.mozbuild
+++ config/system-headers.mozbuild
@@ -1352,5 +1352,10 @@ if CONFIG['OS_TARGET'] == 'Linux' and CONFIG['CPU_ARCH'].startswith('mips'):
'sys/cachectl.h',
]
+if CONFIG['OS_TARGET'] == 'FreeBSD':
+ system_headers += [
+ 'sys/capsicum.h',
+ ]
+
if CONFIG['MOZ_APP_SYSTEM_HEADERS']:
include("../" + CONFIG['MOZ_BUILD_APP'] + "/app-system-headers.mozbuild")
diff --git ipc/chromium/src/base/linux_memfd_defs.h ipc/chromium/src/base/linux_memfd_defs.h
new file mode 100644
index 000000000000..f5b0de1de853
--- /dev/null
+++ ipc/chromium/src/base/linux_memfd_defs.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+#ifndef BASE_LINUX_MEMFD_DEFS_H
+#define BASE_LINUX_MEMFD_DEFS_H
+
+#include <sys/syscall.h>
+
+// glibc before 2.27 didn't have a memfd_create wrapper, and if the
+// build system is old enough then it won't have the syscall number
+// and various related constants either.
+
+#if defined(__x86_64__)
+# define MEMFD_CREATE_NR 319
+#elif defined(__i386__)
+# define MEMFD_CREATE_NR 356
+#elif defined(__aarch64__)
+# define MEMFD_CREATE_NR 279
+#elif defined(__arm__)
+# define MEMFD_CREATE_NR 385
+#elif defined(__powerpc__)
+# define MEMFD_CREATE_NR 360
+#elif defined(__s390__)
+# define MEMFD_CREATE_NR 350
+#elif defined(__mips__)
+# include <sgidefs.h>
+# if _MIPS_SIM == _MIPS_SIM_ABI32
+# define MEMFD_CREATE_NR 4354
+# elif _MIPS_SIM == _MIPS_SIM_ABI64
+# define MEMFD_CREATE_NR 5314
+# elif _MIPS_SIM == _MIPS_SIM_NABI32
+# define MEMFD_CREATE_NR 6318
+# endif // mips subarch
+#endif // arch
+
+#ifdef MEMFD_CREATE_NR
+# ifdef SYS_memfd_create
+static_assert(MEMFD_CREATE_NR == SYS_memfd_create,
+ "MEMFD_CREATE_NR should match the actual SYS_memfd_create value");
+# else // defined here but not in system headers
+# define SYS_memfd_create MEMFD_CREATE_NR
+# endif
+#endif
+
+#ifndef MFD_CLOEXEC
+# define MFD_CLOEXEC 0x0001U
+# define MFD_ALLOW_SEALING 0x0002U
+#endif
+
+#ifndef F_ADD_SEALS
+# ifndef F_LINUX_SPECIFIC_BASE
+# define F_LINUX_SPECIFIC_BASE 1024
+# endif
+# define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
+# define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
+# define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */
+# define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */
+# define F_SEAL_GROW 0x0004 /* prevent file from growing */
+# define F_SEAL_WRITE 0x0008 /* prevent writes */
+#endif
+
+#ifndef F_SEAL_FUTURE_WRITE
+# define F_SEAL_FUTURE_WRITE 0x0010
+#endif
+
+#endif // BASE_LINUX_MEMFD_DEFS_H
diff --git ipc/chromium/src/base/shared_memory.h ipc/chromium/src/base/shared_memory.h
index 93372f4ab333..49d614164a0b 100644
--- ipc/chromium/src/base/shared_memory.h
+++ ipc/chromium/src/base/shared_memory.h
@@ -216,8 +216,9 @@ class SharedMemory {
// If true indicates this came from an external source so needs extra checks
// before being mapped.
bool external_section_ = false;
-#elif defined(OS_POSIX)
+#elif defined(OS_POSIX) && !defined(ANDROID)
mozilla::UniqueFileHandle frozen_file_;
+ bool is_memfd_ = false;
#endif
bool read_only_ = false;
bool freezeable_ = false;
diff --git ipc/chromium/src/base/shared_memory_posix.cc ipc/chromium/src/base/shared_memory_posix.cc
index d5f734ac91b8..e36805aedb89 100644
--- ipc/chromium/src/base/shared_memory_posix.cc
+++ ipc/chromium/src/base/shared_memory_posix.cc
@@ -16,6 +16,18 @@
# include "mozilla/Ashmem.h"
#endif
+#ifdef OS_LINUX
+# include "linux_memfd_defs.h"
+#endif
+
+#ifdef __FreeBSD__
+# include <sys/capsicum.h>
+#endif
+
+#ifdef MOZ_VALGRIND
+# include <valgrind/valgrind.h>
+#endif
+
#include "base/eintr_wrapper.h"
#include "base/logging.h"
#include "base/string_util.h"
@@ -46,11 +58,14 @@ SharedMemory::~SharedMemory() {
bool SharedMemory::SetHandle(SharedMemoryHandle handle, bool read_only) {
DCHECK(!mapped_file_);
+#ifndef ANDROID
DCHECK(!frozen_file_);
+#endif
freezeable_ = false;
mapped_file_.reset(handle.fd);
read_only_ = read_only;
+ // is_memfd_ only matters for freezing, which isn't possible
return true;
}
@@ -62,11 +77,187 @@ bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) {
// static
SharedMemoryHandle SharedMemory::NULLHandle() { return SharedMemoryHandle(); }
-// static
+#ifdef ANDROID
+
+// Android has its own shared memory API, ashmem. It doesn't support
+// POSIX shm_open, and the memfd support (see below) also doesn't work
+// because its SELinux policy prevents the procfs operations we'd use
+// (see bug 1670277 for more details).
+
bool SharedMemory::AppendPosixShmPrefix(std::string* str, pid_t pid) {
-#if defined(ANDROID)
return false;
-#else
+}
+
+bool SharedMemory::CreateInternal(size_t size, bool freezeable) {
+ read_only_ = false;
+
+ DCHECK(size > 0);
+ DCHECK(!mapped_file_);
+
+ int fd = mozilla::android::ashmem_create(nullptr, size);
+ if (fd < 0) {
+ CHROMIUM_LOG(WARNING) << "failed to open shm: " << strerror(errno);
+ return false;
+ }
+
+ mapped_file_.reset(fd);
+ max_size_ = size;
+ freezeable_ = freezeable;
+ return true;
+}
+
+bool SharedMemory::ReadOnlyCopy(SharedMemory* ro_out) {
+ DCHECK(mapped_file_);
+ DCHECK(!read_only_);
+ CHECK(freezeable_);
+
+ if (ro_out == this) {
+ DCHECK(!memory_);
+ }
+
+ if (mozilla::android::ashmem_setProt(mapped_file_.get(), PROT_READ) != 0) {
+ CHROMIUM_LOG(WARNING) << "failed to set ashmem read-only: "
+ << strerror(errno);
+ return false;
+ }
+
+ mozilla::UniqueFileHandle ro_file = std::move(mapped_file_);
+
+ freezeable_ = false;
+ ro_out->Close();
+ ro_out->mapped_file_ = std::move(ro_file);
+ ro_out->max_size_ = max_size_;
+ ro_out->read_only_ = true;
+ ro_out->freezeable_ = false;
+
+ return true;
+}
+
+#else // not Android
+
+// memfd_create is a nonstandard interface for creating anonymous
+// shared memory accessible as a file descriptor but not tied to any
+// filesystem. It first appeared in Linux 3.17, and was adopted by
+// FreeBSD in version 13.
+
+# if !defined(HAVE_MEMFD_CREATE) && defined(OS_LINUX) && \
+ defined(SYS_memfd_create)
+
+// Older libc versions (e.g., glibc before 2.27) don't have the
+// wrapper, but we can supply our own; see `linux_memfd_defs.h`.
+
+static int memfd_create(const char* name, unsigned int flags) {
+ return syscall(SYS_memfd_create, name, flags);
+}
+
+# define HAVE_MEMFD_CREATE 1
+# endif
+
+// memfd supports having "seals" applied to the file, to prevent
+// various types of changes (which apply to all fds referencing the
+// file). Unfortunately, we can't rely on F_SEAL_WRITE to implement
+// Freeze(); see the comments in ReadOnlyCopy() below.
+//
+// Instead, to prevent a child process from regaining write access to
+// a read-only copy, the OS must also provide a way to remove write
+// permissions at the file descriptor level. This next section
+// attempts to accomplish that.
+
+# ifdef HAVE_MEMFD_CREATE
+# ifdef XP_LINUX
+# define USE_MEMFD_CREATE 1
+
+// To create a read-only duplicate of an fd, we can use procfs; the
+// same operation could restore write access, but sandboxing prevents
+// child processes from accessing /proc.
+//
+// (Note: if this ever changes to not use /proc, also reconsider how
+// and if HaveMemfd should check whether this works.)
+
+static int DupReadOnly(int fd) {
+ std::string path = StringPrintf("/proc/self/fd/%d", fd);
+ // procfs opens probably won't EINTR, but checking for it can't hurt
+ return HANDLE_EINTR(open(path.c_str(), O_RDONLY | O_CLOEXEC));
+}
+
+# elif defined(__FreeBSD__)
+# define USE_MEMFD_CREATE 1
+
+// FreeBSD's Capsicum framework allows irrevocably restricting the
+// operations permitted on a file descriptor.
+
+static int DupReadOnly(int fd) {
+ int rofd = dup(fd);
+ if (rofd < 0) {
+ return -1;
+ }
+
+ cap_rights_t rights;
+ cap_rights_init(&rights, CAP_FSTAT, CAP_MMAP_R);
+ if (cap_rights_limit(rofd, &rights) < 0) {
+ int err = errno;
+ close(rofd);
+ errno = err;
+ return -1;
+ }
+
+ return rofd;
+}
+
+# else // unhandled OS
+# warning "OS has memfd_create but no DupReadOnly implementation"
+# endif // OS selection
+# endif // HAVE_MEMFD_CREATE
+
+// Runtime detection for memfd support.
+static bool HaveMemfd() {
+# ifdef USE_MEMFD_CREATE
+ static const bool kHave = [] {
+ mozilla::UniqueFileHandle fd(
+ memfd_create("mozilla-ipc-test", MFD_CLOEXEC | MFD_ALLOW_SEALING));
+ if (!fd) {
+ DCHECK_EQ(errno, ENOSYS);
+ return false;
+ }
+
+ // Verify that DupReadOnly works; on Linux it's known to fail if:
+ //
+ // * SELinux assigns the memfd a type for which this process's
+ // domain doesn't have "open" permission; this is always the
+ // case on Android but could occur on desktop as well
+ //
+ // * /proc (used by the DupReadOnly implementation) isn't mounted,
+ // which is a configuration that the Tor Browser project is
+ // interested in as a way to reduce fingerprinting risk
+ //
+ // Sandboxed processes on Linux also can't use it if sandboxing
+ // has already been started, but that's expected. It should be
+ // safe for sandboxed child processes to use memfd even if an
+ // unsandboxed process couldn't freeze them, because freezing
+ // isn't allowed (or meaningful) for memory created by another
+ // process.
+
+ if (!PR_GetEnv("MOZ_SANDBOXED")) {
+ mozilla::UniqueFileHandle rofd(DupReadOnly(fd.get()));
+ if (!rofd) {
+ CHROMIUM_LOG(WARNING) << "read-only dup failed (" << strerror(errno)
+ << "); not using memfd";
+ return false;
+ }
+ }
+ return true;
+ }();
+ return kHave;
+# else
+ return false;
+# endif // USE_MEMFD_CREATE
+}
+
+// static
+bool SharedMemory::AppendPosixShmPrefix(std::string* str, pid_t pid) {
+ if (HaveMemfd()) {
+ return false;
+ }
*str += '/';
# ifdef OS_LINUX
// The Snap package environment doesn't provide a private /dev/shm
@@ -90,7 +281,6 @@ bool SharedMemory::AppendPosixShmPrefix(std::string* str, pid_t pid) {
// enough for this.
StringAppendF(str, "org.mozilla.ipc.%d.", static_cast<int>(pid));
return true;
-#endif // !ANDROID
}
bool SharedMemory::CreateInternal(size_t size, bool freezeable) {
@@ -102,104 +292,118 @@ bool SharedMemory::CreateInternal(size_t size, bool freezeable) {
mozilla::UniqueFileHandle fd;
mozilla::UniqueFileHandle frozen_fd;
- bool needs_truncate = true;
+ bool is_memfd = false;
+
+# ifdef USE_MEMFD_CREATE
+ if (HaveMemfd()) {
+ const unsigned flags = MFD_CLOEXEC | (freezeable ? MFD_ALLOW_SEALING : 0);
+ fd.reset(memfd_create("mozilla-ipc", flags));
+ if (!fd) {
+ // In general it's too late to fall back here -- in a sandboxed
+ // child process, shm_open is already blocked. And it shouldn't
+ // be necessary.
+ CHROMIUM_LOG(WARNING) << "failed to create memfd: " << strerror(errno);
+ return false;
+ }
+ is_memfd = true;
+ if (freezeable) {
+ frozen_fd.reset(DupReadOnly(fd.get()));
+ if (!frozen_fd) {
+ CHROMIUM_LOG(WARNING)
+ << "failed to create read-only memfd: " << strerror(errno);
+ return false;
+ }
+ }
+ }
+# endif
-#ifdef ANDROID
- // Android has its own shared memory facility:
- fd.reset(mozilla::android::ashmem_create(nullptr, size));
if (!fd) {
- CHROMIUM_LOG(WARNING) << "failed to open shm: " << strerror(errno);
- return false;
- }
- needs_truncate = false;
-#else
- // Generic Unix: shm_open + shm_unlink
- do {
- // The names don't need to be unique, but it saves time if they
- // usually are.
- static mozilla::Atomic<size_t> sNameCounter;
- std::string name;
- CHECK(AppendPosixShmPrefix(&name, getpid()));
- StringAppendF(&name, "%zu", sNameCounter++);
- // O_EXCL means the names being predictable shouldn't be a problem.
- fd.reset(
- HANDLE_EINTR(shm_open(name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600)));
- if (fd) {
- if (freezeable) {
- frozen_fd.reset(HANDLE_EINTR(shm_open(name.c_str(), O_RDONLY, 0400)));
- if (!frozen_fd) {
- int open_err = errno;
- shm_unlink(name.c_str());
- DLOG(FATAL) << "failed to re-open freezeable shm: "
- << strerror(open_err);
+ // Generic Unix: shm_open + shm_unlink
+ do {
+ // The names don't need to be unique, but it saves time if they
+ // usually are.
+ static mozilla::Atomic<size_t> sNameCounter;
+ std::string name;
+ CHECK(AppendPosixShmPrefix(&name, getpid()));
+ StringAppendF(&name, "%zu", sNameCounter++);
+ // O_EXCL means the names being predictable shouldn't be a problem.
+ fd.reset(HANDLE_EINTR(
+ shm_open(name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600)));
+ if (fd) {
+ if (freezeable) {
+ frozen_fd.reset(HANDLE_EINTR(shm_open(name.c_str(), O_RDONLY, 0400)));
+ if (!frozen_fd) {
+ int open_err = errno;
+ shm_unlink(name.c_str());
+ DLOG(FATAL) << "failed to re-open freezeable shm: "
+ << strerror(open_err);
+ return false;
+ }
+ }
+ if (shm_unlink(name.c_str()) != 0) {
+ // This shouldn't happen, but if it does: assume the file is
+ // in fact leaked, and bail out now while it's still 0-length.
+ DLOG(FATAL) << "failed to unlink shm: " << strerror(errno);
return false;
}
}
- if (shm_unlink(name.c_str()) != 0) {
- // This shouldn't happen, but if it does: assume the file is
- // in fact leaked, and bail out now while it's still 0-length.
- DLOG(FATAL) << "failed to unlink shm: " << strerror(errno);
- return false;
- }
- }
- } while (!fd && errno == EEXIST);
-#endif
+ } while (!fd && errno == EEXIST);
+ }
if (!fd) {
CHROMIUM_LOG(WARNING) << "failed to open shm: " << strerror(errno);
return false;
}
- if (needs_truncate) {
-#if defined(HAVE_POSIX_FALLOCATE)
- // Using posix_fallocate will ensure that there's actually space for this
- // file. Otherwise we end up with a sparse file that can give SIGBUS if we
- // run out of space while writing to it.
- int rv;
- {
- // Avoid repeated interruptions of posix_fallocate by the profiler's
- // SIGPROF sampling signal. Indicating "thread sleep" here means we'll
- // get up to one interruption but not more. See bug 1658847 for more.
- // This has to be scoped outside the HANDLE_RV_EINTR retry loop.
- AUTO_PROFILER_THREAD_SLEEP;
- rv = HANDLE_RV_EINTR(
- posix_fallocate(fd.get(), 0, static_cast<off_t>(size)));
- }
- if (rv != 0) {
- if (rv == EOPNOTSUPP || rv == EINVAL || rv == ENODEV) {
- // Some filesystems have trouble with posix_fallocate. For now, we must
- // fallback ftruncate and accept the allocation failures like we do
- // without posix_fallocate.
- // See https://bugzilla.mozilla.org/show_bug.cgi?id=1618914
- int fallocate_errno = rv;
- rv = HANDLE_EINTR(ftruncate(fd.get(), static_cast<off_t>(size)));
- if (rv != 0) {
- CHROMIUM_LOG(WARNING) << "fallocate failed to set shm size: "
- << strerror(fallocate_errno);
- CHROMIUM_LOG(WARNING)
- << "ftruncate failed to set shm size: " << strerror(errno);
- return false;
- }
- } else {
+# if defined(HAVE_POSIX_FALLOCATE)
+ // Using posix_fallocate will ensure that there's actually space for this
+ // file. Otherwise we end up with a sparse file that can give SIGBUS if we
+ // run out of space while writing to it.
+ int rv;
+ {
+ // Avoid repeated interruptions of posix_fallocate by the profiler's
+ // SIGPROF sampling signal. Indicating "thread sleep" here means we'll
+ // get up to one interruption but not more. See bug 1658847 for more.
+ // This has to be scoped outside the HANDLE_RV_EINTR retry loop.
+ AUTO_PROFILER_THREAD_SLEEP;
+ rv =
+ HANDLE_RV_EINTR(posix_fallocate(fd.get(), 0, static_cast<off_t>(size)));
+ }
+ if (rv != 0) {
+ if (rv == EOPNOTSUPP || rv == EINVAL || rv == ENODEV) {
+ // Some filesystems have trouble with posix_fallocate. For now, we must
+ // fallback ftruncate and accept the allocation failures like we do
+ // without posix_fallocate.
+ // See https://bugzilla.mozilla.org/show_bug.cgi?id=1618914
+ int fallocate_errno = rv;
+ rv = HANDLE_EINTR(ftruncate(fd.get(), static_cast<off_t>(size)));
+ if (rv != 0) {
+ CHROMIUM_LOG(WARNING) << "fallocate failed to set shm size: "
+ << strerror(fallocate_errno);
CHROMIUM_LOG(WARNING)
- << "fallocate failed to set shm size: " << strerror(rv);
+ << "ftruncate failed to set shm size: " << strerror(errno);
return false;
}
- }
-#else
- int rv = HANDLE_EINTR(ftruncate(fd.get(), static_cast<off_t>(size)));
- if (rv != 0) {
+ } else {
CHROMIUM_LOG(WARNING)
- << "ftruncate failed to set shm size: " << strerror(errno);
+ << "fallocate failed to set shm size: " << strerror(rv);
return false;
}
-#endif
}
+# else
+ int rv = HANDLE_EINTR(ftruncate(fd.get(), static_cast<off_t>(size)));
+ if (rv != 0) {
+ CHROMIUM_LOG(WARNING) << "ftruncate failed to set shm size: "
+ << strerror(errno);
+ return false;
+ }
+# endif
mapped_file_ = std::move(fd);
frozen_file_ = std::move(frozen_fd);
max_size_ = size;
freezeable_ = freezeable;
+ is_memfd_ = is_memfd;
return true;
}
@@ -212,23 +416,63 @@ bool SharedMemory::ReadOnlyCopy(SharedMemory* ro_out) {
DCHECK(!memory_);
}
- mozilla::UniqueFileHandle ro_file;
-#ifdef ANDROID
- ro_file = std::move(mapped_file_);
- if (mozilla::android::ashmem_setProt(ro_file.get(), PROT_READ) != 0) {
- CHROMIUM_LOG(WARNING) << "failed to set ashmem read-only: "
- << strerror(errno);
- return false;
+# ifdef USE_MEMFD_CREATE
+# ifdef MOZ_VALGRIND
+ // Valgrind allows memfd_create but doesn't understand F_ADD_SEALS.
+ static const bool haveSeals = RUNNING_ON_VALGRIND == 0;
+# else
+ static const bool haveSeals = true;
+# endif
+ static const bool useSeals = !PR_GetEnv("MOZ_SHM_NO_SEALS");
+ if (is_memfd_ && haveSeals && useSeals) {
+ // Seals are added to the file as defense-in-depth. The primary
+ // method of access control is creating a read-only fd (using
+ // procfs in this case) and requiring that sandboxes processes not
+ // have access to /proc/self/fd to regain write permission; this
+ // is the same as with shm_open.
+ //
+ // Unfortunately, F_SEAL_WRITE is unreliable: if the process
+ // forked while there was a writeable mapping, it will inherit a
+ // copy of the mapping, which causes the seal to fail.
+ //
+ // (Also, in the future we may want to split this into separate
+ // classes for mappings and shared memory handles, which would
+ // complicate identifying the case where `F_SEAL_WRITE` would be
+ // possible even in the absence of races with fork.)
+ //
+ // However, Linux 5.1 added F_SEAL_FUTURE_WRITE, which prevents
+ // write operations afterwards, but existing writeable mappings
+ // are unaffected (similar to ashmem protection semantics).
+
+ const int seals = F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL;
+ int sealError = EINVAL;
+
+# ifdef F_SEAL_FUTURE_WRITE
+ sealError =
+ fcntl(mapped_file_.get(), F_ADD_SEALS, seals | F_SEAL_FUTURE_WRITE) == 0
+ ? 0
+ : errno;
+# endif // F_SEAL_FUTURE_WRITE
+ if (sealError == EINVAL) {
+ sealError =
+ fcntl(mapped_file_.get(), F_ADD_SEALS, seals) == 0 ? 0 : errno;
+ }
+ if (sealError != 0) {
+ CHROMIUM_LOG(WARNING) << "failed to seal memfd: " << strerror(errno);
+ return false;
+ }
}
-#else
+# else // !USE_MEMFD_CREATE
+ DCHECK(!is_memfd_);
+# endif
+
DCHECK(frozen_file_);
+ DCHECK(mapped_file_);
mapped_file_ = nullptr;
- ro_file = std::move(frozen_file_);
-#endif
+ mozilla::UniqueFileHandle ro_file = std::move(frozen_file_);
DCHECK(ro_file);
freezeable_ = false;
-
ro_out->Close();
ro_out->mapped_file_ = std::move(ro_file);
ro_out->max_size_ = max_size_;
@@ -238,6 +482,8 @@ bool SharedMemory::ReadOnlyCopy(SharedMemory* ro_out) {
return true;
}
+#endif // not Android
+
bool SharedMemory::Map(size_t bytes, void* fixed_address) {
if (!mapped_file_) {
return false;
@@ -292,10 +538,12 @@ void SharedMemory::Close(bool unmap_view) {
}
mapped_file_ = nullptr;
+#ifndef ANDROID
if (frozen_file_) {
CHROMIUM_LOG(WARNING) << "freezeable shared memory was never frozen";
frozen_file_ = nullptr;
}
+#endif
}
} // namespace base
diff --git ipc/gtest/TestSharedMemory.cpp ipc/gtest/TestSharedMemory.cpp
index 4c8ab0c77592..1474be0ea0d9 100644
--- ipc/gtest/TestSharedMemory.cpp
+++ ipc/gtest/TestSharedMemory.cpp
@@ -13,6 +13,15 @@
#include "mozilla/ipc/SharedMemory.h"
#include "mozilla/ipc/SharedMemoryBasic.h"
+#ifdef XP_LINUX
+# include <errno.h>
+# include <linux/magic.h>
+# include <stdio.h>
+# include <string.h>
+# include <sys/statfs.h>
+# include <sys/utsname.h>
+#endif
+
#ifdef XP_WIN
# include <windows.h>
#endif
@@ -293,4 +302,41 @@ TEST(IPCSharedMemory, BasicIsZero)
}
#endif
+#if defined(XP_LINUX) && !defined(ANDROID)
+// Test that memfd_create is used where expected.
+//
+// More precisely: if memfd_create support is expected, verify that
+// shared memory isn't subject to a filesystem size limit.
+TEST(IPCSharedMemory, IsMemfd)
+{
+ static constexpr int kMajor = 3;
+ static constexpr int kMinor = 17;
+
+ struct utsname uts;
+ ASSERT_EQ(uname(&uts), 0) << strerror(errno);
+ ASSERT_STREQ(uts.sysname, "Linux");
+ int major, minor;
+ ASSERT_EQ(sscanf(uts.release, "%d.%d", &major, &minor), 2);
+ bool expectMemfd = major > kMajor || (major == kMajor && minor >= kMinor);
+
+ base::SharedMemory shm;
+ ASSERT_TRUE(shm.Create(1));
+ UniqueFileHandle fd = shm.TakeHandle();
+ ASSERT_TRUE(fd);
+
+ struct statfs fs;
+ ASSERT_EQ(fstatfs(fd.get(), &fs), 0) << strerror(errno);
+ EXPECT_EQ(fs.f_type, TMPFS_MAGIC);
+ static constexpr decltype(fs.f_blocks) kNoLimit = 0;
+ if (expectMemfd) {
+ EXPECT_EQ(fs.f_blocks, kNoLimit);
+ } else {
+ // On older kernels, we expect the memfd / no-limit test to fail.
+ // (In theory it could succeed if backported memfd support exists;
+ // if that ever happens, this check can be removed.)
+ EXPECT_NE(fs.f_blocks, kNoLimit);
+ }
+}
+#endif
+
} // namespace mozilla
diff --git security/sandbox/linux/SandboxFilter.cpp security/sandbox/linux/SandboxFilter.cpp
index b337a513791e..3017cd967766 100644
--- security/sandbox/linux/SandboxFilter.cpp
+++ security/sandbox/linux/SandboxFilter.cpp
@@ -704,6 +704,10 @@ class SandboxPolicyCommon : public SandboxPolicyBase {
case __NR_munmap:
return Allow();
+ // Shared memory
+ case __NR_memfd_create:
+ return Allow();
+
// ipc::Shmem; also, glibc when creating threads:
case __NR_mprotect:
return Allow();
@@ -1395,11 +1399,6 @@ class ContentSandboxPolicy : public SandboxPolicyCommon {
case __NR_eventfd2:
return Allow();
-# ifdef __NR_memfd_create
- case __NR_memfd_create:
- return Allow();
-# endif
-
# ifdef __NR_rt_tgsigqueueinfo
// Only allow to send signals within the process.
case __NR_rt_tgsigqueueinfo: {

View File

@ -1,80 +0,0 @@
commit 965eb33c5e86
Author: Greg V <greg@unrelenting.technology>
Date: Wed Jan 8 15:06:00 2020 -0800
Bug 1550891 - re-add SHM_ANON support in IPC shared memory, freezing via capabilities
---
config/system-headers.mozbuild | 1 +
ipc/chromium/src/base/shared_memory_posix.cc | 20 +++++++++++++++++---
2 files changed, 18 insertions(+), 3 deletions(-)
diff --git config/system-headers.mozbuild config/system-headers.mozbuild
index 88afca1070f86..beff3e2542c9f 100644
--- config/system-headers.mozbuild
+++ config/system-headers.mozbuild
@@ -816,6 +816,7 @@ system_headers = [
'sys/bitypes.h',
'sys/byteorder.h',
'syscall.h',
+ 'sys/capsicum.h',
'sys/cdefs.h',
'sys/cfgodm.h',
'sys/elf.h',
diff --git ipc/chromium/src/base/shared_memory_posix.cc ipc/chromium/src/base/shared_memory_posix.cc
index 0be9cce0b4bed..89e67483e4c16 100644
--- ipc/chromium/src/base/shared_memory_posix.cc
+++ ipc/chromium/src/base/shared_memory_posix.cc
@@ -16,6 +16,10 @@
# include "mozilla/Ashmem.h"
#endif
+#ifdef __FreeBSD__
+# include <sys/capsicum.h>
+#endif
+
#include "base/eintr_wrapper.h"
#include "base/logging.h"
#include "base/string_util.h"
@@ -77,7 +81,7 @@ SharedMemoryHandle SharedMemory::NULLHandle() { return SharedMemoryHandle(); }
// static
bool SharedMemory::AppendPosixShmPrefix(std::string* str, pid_t pid) {
-#if defined(ANDROID)
+#if defined(ANDROID) || defined(__FreeBSD__)
return false;
#else
*str += '/';
@@ -103,7 +107,7 @@ bool SharedMemory::AppendPosixShmPrefix(std::string* str, pid_t pid) {
// enough for this.
StringAppendF(str, "org.mozilla.ipc.%d.", static_cast<int>(pid));
return true;
-#endif // !ANDROID
+#endif // !ANDROID && !__FreeBSD__
}
bool SharedMemory::CreateInternal(size_t size, bool freezeable) {
@@ -125,6 +129,9 @@ bool SharedMemory::CreateInternal(size_t size, bool freezeable) {
return false;
}
needs_truncate = false;
+#elif defined(__FreeBSD__)
+ // FreeBSD supports anonymous shm_open
+ fd.reset(shm_open(SHM_ANON, O_RDWR, 0600));
#else
// Generic Unix: shm_open + shm_unlink
do {
@@ -224,6 +231,14 @@ bool SharedMemory::ReadOnlyCopy(SharedMemory* ro_out) {
return false;
}
ro_file = mapped_file_;
+#elif defined(__FreeBSD__)
+ cap_rights_t rights;
+ cap_rights_init(&rights, CAP_MMAP_R);
+ if (cap_rights_limit(mapped_file_, &rights) != 0) {
+ CHROMIUM_LOG(WARNING) << "failed to freeze shm: " << strerror(errno);
+ return false;
+ }
+ ro_file = mapped_file_;
#else
DCHECK(frozen_file_ >= 0);
DCHECK(mapped_file_ >= 0);

View File

@ -4,7 +4,7 @@ https://bug1612184.bmoattachments.org/attachment.cgi?id=9126363
diff -r 388a4d04e911 media/webrtc/gn-configs/ppc64_False_ppc64_freebsd.json
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ media/webrtc/gn-configs/ppc64_False_ppc64_freebsd.json Thu Feb 13 11:11:51 2020 +0100
+++ dom/media/webrtc/third_party_build/gn-configs/ppc64_False_ppc64_freebsd.json Thu Feb 13 11:11:51 2020 +0100
@@ -0,0 +1,13237 @@
+{
+ "gn_gen_args": {
@ -13246,7 +13246,7 @@ diff -r 388a4d04e911 media/webrtc/gn-configs/ppc64_False_ppc64_freebsd.json
\ No newline at end of file
diff -r 388a4d04e911 media/webrtc/gn-configs/ppc64_True_ppc64_freebsd.json
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ media/webrtc/gn-configs/ppc64_True_ppc64_freebsd.json Thu Feb 13 11:11:51 2020 +0100
+++ dom/media/webrtc/third_party_build/gn-configs/ppc64_True_ppc64_freebsd.json Thu Feb 13 11:11:51 2020 +0100
@@ -0,0 +1,12693 @@
+{
+ "gn_gen_args": {
@ -25943,17 +25943,17 @@ diff -r 388a4d04e911 media/webrtc/gn-configs/ppc64_True_ppc64_freebsd.json
+}
\ No newline at end of file
diff -r 388a4d04e911 media/webrtc/trunk/webrtc/moz.build
--- media/webrtc/trunk/webrtc/moz.build Wed Jan 29 05:21:52 2020 +0000
+++ media/webrtc/trunk/webrtc/moz.build Thu Feb 13 11:12:15 2020 +0100
@@ -291,6 +291,13 @@
"/media/webrtc/trunk/webrtc/modules/video_processing/video_processing_neon_gn"
--- third_party/libwebrtc/webrtc/moz.build.orig 2020-11-10 17:07:54 UTC
+++ third_party/libwebrtc/webrtc/moz.build
@@ -312,6 +312,13 @@ if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"]
"/third_party/libwebrtc/webrtc/modules/video_processing/video_processing_neon_gn"
]
+if CONFIG["CPU_ARCH"] == "ppc64" and CONFIG["OS_TARGET"] == "FreeBSD":
+
+ DIRS += [
+ "/media/webrtc/trunk/webrtc/api/audio_codecs/isac/audio_decoder_isac_float_gn",
+ "/media/webrtc/trunk/webrtc/api/audio_codecs/isac/audio_encoder_isac_float_gn"
+ "/third_party/libwebrtc/webrtc/api/audio_codecs/isac/audio_decoder_isac_float_gn",
+ "/third_party/libwebrtc/webrtc/api/audio_codecs/isac/audio_encoder_isac_float_gn"
+ ]
+
if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "FreeBSD":