public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
From: Than Ngo <than@fedoraproject.org>
To: git-commits@fedoraproject.org
Subject: [rpms/chromium] epel9-next: Merge #46 `Fix flatpak build`
Date: Fri, 07 Aug 2026 16:07:18 GMT [thread overview]
Message-ID: <178611883888.1.6420532743217227663.rpms-chromium-0c209b92ae81@fedoraproject.org> (raw)
A new commit has been pushed.
Repo : rpms/chromium
Branch : epel9-next
Commit : 0c209b92ae8148011ecc9a6989f01c27077fd09c
Author : Than Ngo <than@fedoraproject.org>
Date : 2025-01-27T16:13:25+00:00
Stats : +1784/-70 in 7 file(s)
URL : https://src.fedoraproject.org/rpms/chromium/c/0c209b92ae8148011ecc9a6989f01c27077fd09c?branch=epel9-next
Log:
Merge #46 `Fix flatpak build`
---
diff --git a/chromium.spec b/chromium.spec
index d36dcb2..0359a29 100644
--- a/chromium.spec
+++ b/chromium.spec
@@ -37,12 +37,18 @@
# enable|disable chromedriver
%global build_chromedriver 1
+%if 0%{?flatpak}
+%global build_chromedriver 0
+%endif
# enable|disable headless client build
%global build_headless 1
%ifarch ppc64le
%global build_headless 0
%endif
+%if 0%{?flatpak}
+%global build_headless 0
+%endif
# enable|disable chrome-remote-desktop build
%global build_remoting 0
@@ -439,6 +445,12 @@ Patch413: fix-unknown-warning-option-messages.diff
Patch414: cargo-add-ppc64.diff
Patch415: add-ppc64-pthread-stack-size.patch
+# flatpak sandbox patches from
+# https://github.com/flathub/org.chromium.Chromium/tree/master/patches/chromium
+Patch416: flatpak-Add-initial-sandbox-support.patch
+Patch417: flatpak-Adjust-paths-for-the-sandbox.patch
+Patch418: flatpak-Expose-Widevine-into-the-sandbox.patch
+
# upstream patches
# Use chromium-latest.py to generate clean tarball from released build tarballs, found here:
@@ -663,7 +675,7 @@ BuildRequires: libXNVCtrl-devel
%endif
# One of the python scripts invokes git to look for a hash. So helpful.
-BuildRequires: /usr/bin/git
+BuildRequires: git-core
BuildRequires: hwdata
BuildRequires: kernel-headers
%if ! %{bundlelibevent}
@@ -779,7 +791,7 @@ Requires: nss-mdns%{_isa}
# GTK modules it expects to find for some reason.
Requires: libcanberra-gtk3%{_isa}
-%if 0%{?fedora}
+%if 0%{?fedora} && %{undefined flatpak}
# This enables support for u2f tokens
Requires: u2f-hidraw-policy
%endif
@@ -920,9 +932,11 @@ Provides: bundled(xdg-mime)
Provides: bundled(xdg-user-dirs)
# Provides: bundled(zlib) = 1.2.11
+%if %{undefined flatpak}
# For selinux scriptlet
Requires(post): /usr/sbin/semanage
Requires(post): /usr/sbin/restorecon
+%endif
%description
Chromium is an open-source web browser, powered by WebKit (Blink).
@@ -1131,6 +1145,12 @@ Qt6 UI for chromium.
%patch -P415 -p1 -b .add-ppc64-pthread-stack-size
%endif
+%if 0%{?flatpak}
+%patch -P416 -p1 -b .flatpak-initial-sandbox
+%patch -P417 -p1 -b .flatpak-sandbox-paths
+%patch -P418 -p1 -b .flatpak-widevine
+%endif
+
# Change shebang in all relevant files in this directory and all subdirectories
# See `man find` for how the `-exec command {} +` syntax works
find -type f \( -iname "*.py" \) -exec sed -i '1s=^#! */usr/bin/\(python\|env python\)[23]\?=#!%{chromium_pybin}=' {} +
@@ -1151,12 +1171,12 @@ find -type f \( -iname "*.py" \) -exec sed -i '1s=^#! */usr/bin/\(python\|env py
popd
%else
mkdir -p third_party/node/linux/node-linux-x64/bin
- ln -s %{_bindir}/node third_party/node/linux/node-linux-x64/bin/node
+ ln -s $(which node) third_party/node/linux/node-linux-x64/bin/node
%endif
# Get rid of the bundled esbuild
%if 0%{?fedora}
- ln -sf %{_bindir}/esbuild third_party/devtools-frontend/src/third_party/esbuild/esbuild
+ ln -sf $(which esbuild) third_party/devtools-frontend/src/third_party/esbuild/esbuild
%else
%ifarch x86_64
tar -zxf %{SOURCE14} --directory %{_tmppath}
@@ -1171,7 +1191,7 @@ popd
rm -rf buildtools/third_party/eu-strip/bin/eu-strip
# Replace it with a symlink to the Fedora copy
-ln -s %{_bindir}/eu-strip buildtools/third_party/eu-strip/bin/eu-strip
+ln -s $(which eu-strip) buildtools/third_party/eu-strip/bin/eu-strip
%if %{bundlelibusbx}
# no hackity hack hack
@@ -1179,7 +1199,7 @@ ln -s %{_bindir}/eu-strip buildtools/third_party/eu-strip/bin/eu-strip
# hackity hack hack
rm -rf third_party/libusb/src/libusb/libusb.h
# we _shouldn't need to do this, but it looks like we do.
-cp -a %{_includedir}/libusb-1.0/libusb.h third_party/libusb/src/libusb/libusb.h
+cp -a $(pkg-config --variable=includedir libusb-1.0)/libusb-1.0/libusb.h third_party/libusb/src/libusb/libusb.h
%endif
# Hard code extra version
@@ -1243,7 +1263,8 @@ export RUSTC_BOOTSTRAP=1
# set rustc version
rustc_version="$(rustc --version)"
# set rust bindgen root
-rust_bindgen_root="%{_prefix}"
+rust_bindgen_root="$(which bindgen | sed 's#/bin/.*##')"
+rust_sysroot_absolute="$(rustc --print sysroot)"
# set clang version
clang_version="$(clang --version | sed -n 's/clang version //p' | cut -d. -f1)"
@@ -1287,7 +1308,7 @@ CHROMIUM_CORE_GN_DEFINES+=' clang_use_chrome_plugins=false'
CHROMIUM_CORE_GN_DEFINES+=' use_lld=true'
# enable system rust
-CHROMIUM_CORE_GN_DEFINES+=' rust_sysroot_absolute="%{_prefix}"'
+CHROMIUM_CORE_GN_DEFINES+=" rust_sysroot_absolute=\"$rust_sysroot_absolute\""
CHROMIUM_CORE_GN_DEFINES+=" rust_bindgen_root=\"$rust_bindgen_root\""
CHROMIUM_CORE_GN_DEFINES+=" rustc_version=\"$rustc_version\""
@@ -1339,13 +1360,13 @@ CHROMIUM_BROWSER_GN_DEFINES+=' rtc_use_h264=false'
CHROMIUM_BROWSER_GN_DEFINES+=' use_kerberos=true'
%if %{use_qt}
-CHROMIUM_BROWSER_GN_DEFINES+=' use_qt=true moc_qt5_path="%{_libdir}/qt5/bin/"'
+CHROMIUM_BROWSER_GN_DEFINES+=" use_qt=true moc_qt5_path=\"$(%{_qt5_qmake} -query QT_HOST_BINS)\""
%else
CHROMIUM_BROWSER_GN_DEFINES+=' use_qt=false'
%endif
%if %{use_qt6}
-CHROMIUM_BROWSER_GN_DEFINES+=' use_qt6=true moc_qt6_path="%{_libdir}/qt6/libexec/"'
+CHROMIUM_BROWSER_GN_DEFINES+=" use_qt6=true moc_qt6_path=\"$(%{_qt6_qmake} -query QT_HOST_LIBEXECS)\""
%else
CHROMIUM_BROWSER_GN_DEFINES+=' use_qt6=false'
%endif
@@ -1514,7 +1535,7 @@ fi
%if %{bootstrap}
tools/gn/bootstrap/bootstrap.py --gn-gen-args="$CHROMIUM_CORE_GN_DEFINES $CHROMIUM_BROWSER_GN_DEFINES"
%else
-mkdir -p %{chromebuilddir} && cp -a %{_bindir}/gn %{chromebuilddir}/
+mkdir -p %{chromebuilddir} && cp -a $(which gn) %{chromebuilddir}/
%endif
%{chromebuilddir}/gn --script-executable=%{chromium_pybin} gen --args="$CHROMIUM_CORE_GN_DEFINES $CHROMIUM_BROWSER_GN_DEFINES" %{chromebuilddir}
@@ -1738,6 +1759,7 @@ cp -a %{SOURCE9} %{buildroot}%{_datadir}/gnome-control-center/default-apps/
# README.fedora
cp %{SOURCE1} .
+%if %{undefined flatpak}
%post
# Set SELinux labels - semanage itself will adjust the lib directory naming
# But only do it when selinux is enabled, otherwise, it gets noisy.
@@ -1747,6 +1769,7 @@ if selinuxenabled; then
semanage fcontext -a -t chrome_sandbox_exec_t /usr/lib/chrome-sandbox &>/dev/null || :
restorecon -R -v %{chromium_path}/%{chromium_browser_channel} &>/dev/null || :
fi
+%endif
%if %{build_remoting}
%pretrans -n chrome-remote-desktop -p <lua>
diff --git a/flatpak-Add-initial-sandbox-support.patch b/flatpak-Add-initial-sandbox-support.patch
new file mode 100644
index 0000000..dae2d94
--- /dev/null
+++ b/flatpak-Add-initial-sandbox-support.patch
@@ -0,0 +1,1325 @@
+From ab11528f26a212417b0b6084b52c02e992fe43f7 Mon Sep 17 00:00:00 2001
+From: Ryan Gonzalez <rymg19@gmail.com>
+Date: Tue, 17 Mar 2020 13:18:27 -0500
+Subject: [PATCH] flatpak: Add initial sandbox support
+
+---
+ .gitignore | 1 +
+ base/threading/thread_restrictions.h | 5 +
+ .../sandbox_internals/sandbox_internals.ts | 4 +
+ .../ui/webui/sandbox/sandbox_internals_ui.cc | 6 +-
+ content/browser/child_process_host_impl.cc | 8 +-
+ .../zygote_host/zygote_host_impl_linux.cc | 39 +-
+ .../zygote_host/zygote_host_impl_linux.h | 1 +
+ content/zygote/zygote_linux.cc | 6 +-
+ content/zygote/zygote_linux.h | 2 +
+ content/zygote/zygote_main_linux.cc | 16 +-
+ sandbox/linux/BUILD.gn | 10 +-
+ sandbox/linux/services/flatpak_pid_map.cc | 57 ++
+ sandbox/linux/services/flatpak_pid_map.h | 46 ++
+ sandbox/linux/services/flatpak_sandbox.cc | 576 ++++++++++++++++++
+ sandbox/linux/services/flatpak_sandbox.h | 118 ++++
+ sandbox/policy/BUILD.gn | 3 +
+ sandbox/policy/linux/sandbox_linux.cc | 8 +
+ sandbox/policy/linux/sandbox_linux.h | 8 +
+ .../service_process_launcher.cc | 12 +-
+ 19 files changed, 907 insertions(+), 19 deletions(-)
+ create mode 100644 sandbox/linux/services/flatpak_pid_map.cc
+ create mode 100644 sandbox/linux/services/flatpak_pid_map.h
+ create mode 100644 sandbox/linux/services/flatpak_sandbox.cc
+ create mode 100644 sandbox/linux/services/flatpak_sandbox.h
+
+diff --git a/.gitignore b/.gitignore
+index 9056030523807..2c13d0ad5f1c7 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -75,6 +75,7 @@ vs-chromium-project.txt
+ /.android_emulator/
+ /.clangd/
+ /.clangd-index/
++/.flatpak-builder/
+ # Settings directories for eclipse
+ /.externalToolBuilders/
+ /.settings/
+diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h
+index 149838be725f2..81034acc71e97 100644
+--- a/base/threading/thread_restrictions.h
++++ b/base/threading/thread_restrictions.h
+@@ -407,6 +407,9 @@ class ScopedAllowThreadJoinForWebRtcTransport;
+ namespace rlz_lib {
+ class FinancialPing;
+ }
++namespace sandbox {
++class FlatpakSandbox;
++}
+ namespace service_manager {
+ class ServiceProcessLauncher;
+ }
+@@ -649,6 +652,7 @@ class BASE_EXPORT ScopedAllowBlocking {
+ friend class remoting::
+ ScopedBypassIOThreadRestrictions; // http://crbug.com/1144161
+ friend class remoting::ScopedAllowBlockingForCrashReporting;
++ friend class sandbox::FlatpakSandbox;
+ friend class ui::DrmDisplayHostManager;
+ friend class ui::ScopedAllowBlockingForGbmSurface;
+ friend class ui::SelectFileDialogLinux;
+@@ -792,6 +796,7 @@ class BASE_EXPORT ScopedAllowBaseSyncPrimitives {
+ friend class rlz_lib::FinancialPing;
+ friend class shell_integration_linux::
+ LaunchXdgUtilityScopedAllowBaseSyncPrimitives;
++ friend class sandbox::FlatpakSandbox;
+ friend class storage::ObfuscatedFileUtil;
+ friend class syncer::HttpBridge;
+ friend class syncer::GetLocalChangesRequest;
+diff --git a/chrome/browser/resources/sandbox_internals/sandbox_internals.ts b/chrome/browser/resources/sandbox_internals/sandbox_internals.ts
+index f6d2f3f0bc41c..fcc58c6735eaa 100644
+--- a/chrome/browser/resources/sandbox_internals/sandbox_internals.ts
++++ b/chrome/browser/resources/sandbox_internals/sandbox_internals.ts
+@@ -140,6 +140,7 @@ function addGoodBadRow(name: string, result: boolean): HTMLElement {
+ function linuxHandler() {
+ const suidSandbox = loadTimeData.getBoolean('suid');
+ const nsSandbox = loadTimeData.getBoolean('userNs');
++ const flatpakSandbox = loadTimeData.getBoolean('flatpak');
+
+ let layer1SandboxType = 'None';
+ let layer1SandboxCssClass = StatusClass.BAD;
+@@ -149,6 +150,9 @@ function linuxHandler() {
+ } else if (nsSandbox) {
+ layer1SandboxType = 'Namespace';
+ layer1SandboxCssClass = StatusClass.GOOD;
++ } else if (flatpakSandbox) {
++ layer1SandboxType = 'Flatpak';
++ layer1SandboxCssClass = StatusClass.GOOD;
+ }
+
+ addStatusRow('Layer 1 Sandbox', layer1SandboxType, layer1SandboxCssClass);
+diff --git a/chrome/browser/ui/webui/sandbox/sandbox_internals_ui.cc b/chrome/browser/ui/webui/sandbox/sandbox_internals_ui.cc
+index 82aa27787a5e0..32bf674f33da6 100644
+--- a/chrome/browser/ui/webui/sandbox/sandbox_internals_ui.cc
++++ b/chrome/browser/ui/webui/sandbox/sandbox_internals_ui.cc
+@@ -20,6 +20,7 @@
+ #include "content/public/browser/web_contents.h"
+ #include "content/public/browser/web_ui.h"
+ #include "content/public/browser/web_ui_data_source.h"
++#include "sandbox/policy/linux/sandbox_linux.h"
+ #include "services/network/public/mojom/content_security_policy.mojom.h"
+
+ #if BUILDFLAG(IS_WIN)
+@@ -46,6 +47,8 @@ static void SetSandboxStatusData(content::WebUIDataSource* source) {
+
+ source->AddBoolean("suid", status & sandbox::policy::SandboxLinux::kSUID);
+ source->AddBoolean("userNs", status & sandbox::policy::SandboxLinux::kUserNS);
++ source->AddBoolean("flatpak",
++ status & sandbox::policy::SandboxLinux::kFlatpak);
+ source->AddBoolean("pidNs", status & sandbox::policy::SandboxLinux::kPIDNS);
+ source->AddBoolean("netNs", status & sandbox::policy::SandboxLinux::kNetNS);
+ source->AddBoolean("seccompBpf",
+@@ -63,7 +66,8 @@ static void SetSandboxStatusData(content::WebUIDataSource* source) {
+
+ // Require either the setuid or namespace sandbox for our first-layer sandbox.
+ bool good_layer1 = (status & sandbox::policy::SandboxLinux::kSUID ||
+- status & sandbox::policy::SandboxLinux::kUserNS) &&
++ status & sandbox::policy::SandboxLinux::kUserNS ||
++ status & sandbox::policy::SandboxLinux::kFlatpak) &&
+ status & sandbox::policy::SandboxLinux::kPIDNS &&
+ status & sandbox::policy::SandboxLinux::kNetNS;
+ // A second-layer sandbox is also required to be adequately sandboxed.
+diff --git a/content/browser/child_process_host_impl.cc b/content/browser/child_process_host_impl.cc
+index 95df576580a9e..8d5e0694660b6 100644
+--- a/content/browser/child_process_host_impl.cc
++++ b/content/browser/child_process_host_impl.cc
+@@ -45,6 +45,7 @@
+
+ #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
+ #include "base/linux_util.h"
++#include "sandbox/linux/services/flatpak_sandbox.h"
+ #elif BUILDFLAG(IS_MAC)
+ #include "base/apple/foundation_util.h"
+ #include "content/browser/mac_helpers.h"
+@@ -78,7 +79,12 @@ base::FilePath ChildProcessHost::GetChildPath(int flags) {
+ #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
+ // Use /proc/self/exe rather than our known binary path so updates
+ // can't swap out the binary from underneath us.
+- if (child_path.empty() && flags & CHILD_ALLOW_SELF) {
++ // This is not needed for Flatpaks, where updates are going to be in
++ // a new hardlink tree.
++ if ((child_path.empty() &&
++ sandbox::FlatpakSandbox::GetInstance()->GetSandboxLevel() ==
++ sandbox::FlatpakSandbox::SandboxLevel::kNone) &&
++ flags & CHILD_ALLOW_SELF) {
+ child_path = base::FilePath(base::kProcSelfExe);
+ }
+ #endif
+diff --git a/content/browser/zygote_host/zygote_host_impl_linux.cc b/content/browser/zygote_host/zygote_host_impl_linux.cc
+index 8eca918b65cbe..1703fb6ade044 100644
+--- a/content/browser/zygote_host/zygote_host_impl_linux.cc
++++ b/content/browser/zygote_host/zygote_host_impl_linux.cc
+@@ -12,6 +12,7 @@
+ #include "base/logging.h"
+ #include "base/posix/unix_domain_socket.h"
+ #include "base/process/kill.h"
++#include "base/process/launch.h"
+ #include "base/process/memory.h"
+ #include "base/strings/string_number_conversions.h"
+ #include "base/types/fixed_array.h"
+@@ -22,6 +23,7 @@
+ #include "content/common/zygote/zygote_handle_impl_linux.h"
+ #include "content/public/common/zygote/zygote_handle.h"
+ #include "sandbox/linux/services/credentials.h"
++#include "sandbox/linux/services/flatpak_sandbox.h"
+ #include "sandbox/linux/services/namespace_sandbox.h"
+ #include "sandbox/linux/suid/client/setuid_sandbox_host.h"
+ #include "sandbox/linux/suid/common/sandbox.h"
+@@ -72,6 +74,7 @@ ZygoteHostImpl::ZygoteHostImpl()
+ : use_namespace_sandbox_(false),
+ use_suid_sandbox_(false),
+ use_suid_sandbox_for_adj_oom_score_(false),
++ use_flatpak_sandbox_(false),
+ sandbox_binary_(),
+ zygote_pids_lock_(),
+ zygote_pids_() {}
+@@ -110,9 +113,12 @@ void ZygoteHostImpl::Init(const base::CommandLine& command_line) {
+ sandbox_binary_ = setuid_sandbox_host->GetSandboxBinaryPath().value();
+ }
+
+- if (!command_line.HasSwitch(
+- sandbox::policy::switches::kDisableNamespaceSandbox) &&
+- sandbox::Credentials::CanCreateProcessInNewUserNS()) {
++ if (sandbox::FlatpakSandbox::GetInstance()->GetSandboxLevel() !=
++ sandbox::FlatpakSandbox::SandboxLevel::kNone) {
++ use_flatpak_sandbox_ = true;
++ } else if (!command_line.HasSwitch(
++ sandbox::policy::switches::kDisableNamespaceSandbox) &&
++ sandbox::Credentials::CanCreateProcessInNewUserNS()) {
+ use_namespace_sandbox_ = true;
+ } else if (!command_line.HasSwitch(
+ sandbox::policy::switches::kDisableSetuidSandbox) &&
+@@ -183,10 +189,16 @@ pid_t ZygoteHostImpl::LaunchZygote(
+ sandbox_host->SetupLaunchEnvironment();
+ }
+
+- base::Process process =
+- (is_sandboxed_zygote && use_namespace_sandbox_)
+- ? sandbox::NamespaceSandbox::LaunchProcess(*cmd_line, options)
+- : base::LaunchProcess(*cmd_line, options);
++ base::Process process;
++ if (is_sandboxed_zygote && use_namespace_sandbox_) {
++ process = sandbox::NamespaceSandbox::LaunchProcess(*cmd_line, options);
++ } else if (is_sandboxed_zygote && use_flatpak_sandbox_) {
++ process = sandbox::FlatpakSandbox::GetInstance()->LaunchProcess(*cmd_line,
++ options);
++ } else {
++ process = base::LaunchProcess(*cmd_line, options);
++ }
++
+ CHECK(process.IsValid()) << "Failed to launch zygote process";
+
+ dummy_fd.reset();
+@@ -195,7 +207,8 @@ pid_t ZygoteHostImpl::LaunchZygote(
+
+ pid_t pid = process.Pid();
+
+- if (is_sandboxed_zygote && (use_namespace_sandbox_ || use_suid_sandbox_)) {
++ if (is_sandboxed_zygote &&
++ (use_namespace_sandbox_ || use_suid_sandbox_ || use_flatpak_sandbox_)) {
+ // The namespace and SUID sandbox will execute the zygote in a new
+ // PID namespace, and the main zygote process will then fork from
+ // there. Watch now our elaborate dance to find and validate the
+@@ -223,7 +236,11 @@ pid_t ZygoteHostImpl::LaunchZygote(
+
+ if (real_pid != pid) {
+ // Reap the sandbox.
+- base::EnsureProcessGetsReaped(std::move(process));
++ if (use_flatpak_sandbox_) {
++ sandbox::FlatpakSandbox::GetInstance()->IgnoreExitStatus(pid);
++ } else {
++ base::EnsureProcessGetsReaped(base::Process(pid));
++ }
+ }
+ pid = real_pid;
+ }
+@@ -274,6 +291,10 @@ void ZygoteHostImpl::AdjustRendererOOMScore(base::ProcessHandle pid,
+ selinux_valid = true;
+ }
+
++ // Flatpaks cannot modify their OOM score.
++ if (use_flatpak_sandbox_)
++ return;
++
+ if (!use_suid_sandbox_for_adj_oom_score_) {
+ if (!base::AdjustOOMScore(pid, score))
+ PLOG(ERROR) << "Failed to adjust OOM score of renderer with pid " << pid;
+diff --git a/content/browser/zygote_host/zygote_host_impl_linux.h b/content/browser/zygote_host/zygote_host_impl_linux.h
+index 720d823d4a695..ad470963693c4 100644
+--- a/content/browser/zygote_host/zygote_host_impl_linux.h
++++ b/content/browser/zygote_host/zygote_host_impl_linux.h
+@@ -70,6 +70,7 @@ class CONTENT_EXPORT ZygoteHostImpl : public ZygoteHost {
+ bool use_namespace_sandbox_;
+ bool use_suid_sandbox_;
+ bool use_suid_sandbox_for_adj_oom_score_;
++ bool use_flatpak_sandbox_;
+ std::string sandbox_binary_;
+
+ // This lock protects the |zygote_pids_| set.
+diff --git a/content/zygote/zygote_linux.cc b/content/zygote/zygote_linux.cc
+index bdcb36f7eb2fe..239a6462e4b41 100644
+--- a/content/zygote/zygote_linux.cc
++++ b/content/zygote/zygote_linux.cc
+@@ -127,7 +127,7 @@ bool Zygote::ProcessRequests() {
+ PCHECK(sigaddset(&sigset, SIGCHLD) == 0);
+ PCHECK(sigprocmask(SIG_BLOCK, &sigset, &orig_sigmask) == 0);
+
+- if (UsingSUIDSandbox() || UsingNSSandbox()) {
++ if (UsingSUIDSandbox() || UsingNSSandbox() || UsingFlatpakSandbox()) {
+ // Let the ZygoteHost know we are ready to go.
+ // The receiving code is in
+ // content/browser/zygote_host/zygote_host_impl_linux.cc.
+@@ -233,6 +233,10 @@ bool Zygote::UsingNSSandbox() const {
+ return sandbox_flags_ & sandbox::policy::SandboxLinux::kUserNS;
+ }
+
++bool Zygote::UsingFlatpakSandbox() const {
++ return sandbox_flags_ & sandbox::policy::SandboxLinux::kFlatpak;
++}
++
+ bool Zygote::HandleRequestFromBrowser(int fd) {
+ std::vector<base::ScopedFD> fds;
+ uint8_t buf[kZygoteMaxMessageLength];
+diff --git a/content/zygote/zygote_linux.h b/content/zygote/zygote_linux.h
+index 165b758efc899..961afa73f66f5 100644
+--- a/content/zygote/zygote_linux.h
++++ b/content/zygote/zygote_linux.h
+@@ -64,6 +64,8 @@ class Zygote {
+ bool UsingSUIDSandbox() const;
+ // Returns true if the NS sandbox is active.
+ bool UsingNSSandbox() const;
++ // Returns true if the Flatpak sandbox is active.
++ bool UsingFlatpakSandbox() const;
+
+ // ---------------------------------------------------------------------------
+ // Requests from the browser...
+diff --git a/content/zygote/zygote_main_linux.cc b/content/zygote/zygote_main_linux.cc
+index c7ee91878e6dd..9c2c7a04bd968 100644
+--- a/content/zygote/zygote_main_linux.cc
++++ b/content/zygote/zygote_main_linux.cc
+@@ -35,6 +35,7 @@
+ #include "content/public/common/zygote/zygote_fork_delegate_linux.h"
+ #include "content/zygote/zygote_linux.h"
+ #include "sandbox/linux/services/credentials.h"
++#include "sandbox/linux/services/flatpak_sandbox.h"
+ #include "sandbox/linux/services/init_process_reaper.h"
+ #include "sandbox/linux/services/libc_interceptor.h"
+ #include "sandbox/linux/services/namespace_sandbox.h"
+@@ -135,6 +136,7 @@ static void EnterNamespaceSandbox(sandbox::policy::SandboxLinux* linux_sandbox,
+
+ static void EnterLayerOneSandbox(sandbox::policy::SandboxLinux* linux_sandbox,
+ const bool using_layer1_sandbox,
++ const bool using_flatpak_sandbox,
+ base::OnceClosure post_fork_parent_callback) {
+ DCHECK(linux_sandbox);
+
+@@ -154,7 +156,8 @@ static void EnterLayerOneSandbox(sandbox::policy::SandboxLinux* linux_sandbox,
+ } else if (sandbox::NamespaceSandbox::InNewUserNamespace()) {
+ EnterNamespaceSandbox(linux_sandbox, std::move(post_fork_parent_callback));
+ } else {
+- CHECK(!using_layer1_sandbox);
++ // The Flatpak sandbox means that we're fully sandboxed from the start.
++ CHECK(!using_layer1_sandbox || using_flatpak_sandbox);
+ }
+ }
+
+@@ -178,8 +181,11 @@ bool ZygoteMain(
+ linux_sandbox->setuid_sandbox_client()->IsSuidSandboxChild();
+ const bool using_namespace_sandbox =
+ sandbox::NamespaceSandbox::InNewUserNamespace();
++ const bool using_flatpak_sandbox =
++ sandbox::FlatpakSandbox::GetInstance()->GetSandboxLevel() ==
++ sandbox::FlatpakSandbox::SandboxLevel::kRestricted;
+ const bool using_layer1_sandbox =
+- using_setuid_sandbox || using_namespace_sandbox;
++ using_setuid_sandbox || using_namespace_sandbox || using_flatpak_sandbox;
+
+ if (using_setuid_sandbox) {
+ linux_sandbox->setuid_sandbox_client()->CloseDummyFile();
+@@ -206,7 +212,7 @@ bool ZygoteMain(
+
+ // Turn on the first layer of the sandbox if the configuration warrants it.
+ EnterLayerOneSandbox(
+- linux_sandbox, using_layer1_sandbox,
++ linux_sandbox, using_layer1_sandbox, using_flatpak_sandbox,
+ base::BindOnce(CloseFds, linux_sandbox->GetFileDescriptorsToClose()));
+
+ const int sandbox_flags = linux_sandbox->GetStatus();
+@@ -218,6 +224,10 @@ bool ZygoteMain(
+ !!(sandbox_flags & sandbox::policy::SandboxLinux::kUserNS);
+ CHECK_EQ(using_namespace_sandbox, namespace_sandbox_engaged);
+
++ const bool flatpak_sandbox_engaged =
++ !!(sandbox_flags & sandbox::policy::SandboxLinux::kFlatpak);
++ CHECK_EQ(using_flatpak_sandbox, flatpak_sandbox_engaged);
++
+ Zygote zygote(sandbox_flags, std::move(fork_delegates),
+ base::GlobalDescriptors::Descriptor(
+ static_cast<uint32_t>(kSandboxIPCChannel), GetSandboxFD()));
+diff --git a/sandbox/linux/BUILD.gn b/sandbox/linux/BUILD.gn
+index 97e3deed4f2b9..61916ed9805d3 100644
+--- a/sandbox/linux/BUILD.gn
++++ b/sandbox/linux/BUILD.gn
+@@ -311,6 +311,10 @@ if (is_linux || is_chromeos) {
+
+ component("sandbox_services") {
+ sources = [
++ "services/flatpak_pid_map.cc",
++ "services/flatpak_pid_map.h",
++ "services/flatpak_sandbox.cc",
++ "services/flatpak_sandbox.h",
+ "services/init_process_reaper.cc",
+ "services/init_process_reaper.h",
+ "services/proc_util.cc",
+@@ -329,8 +333,10 @@ component("sandbox_services") {
+
+ defines = [ "SANDBOX_IMPLEMENTATION" ]
+
+- public_deps = [ "//sandbox:sandbox_export" ]
+- deps = [ "//base" ]
++ public_deps = [
++ "//dbus",
++ "//sandbox:sandbox_export",
++ ]
+
+ if (compile_credentials) {
+ sources += [
+diff --git a/sandbox/linux/services/flatpak_pid_map.cc b/sandbox/linux/services/flatpak_pid_map.cc
+new file mode 100644
+index 0000000000000..58b2ab552385b
+--- /dev/null
++++ b/sandbox/linux/services/flatpak_pid_map.cc
+@@ -0,0 +1,57 @@
++// Copyright 2020 The Chromium Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++
++#include "sandbox/linux/services/flatpak_pid_map.h"
++
++namespace sandbox {
++
++bool FlatpakPidMap::Insert(PidPair pair) {
++ if (external_to_relative_.contains(pair.external) ||
++ relative_to_external_.contains(pair.relative)) {
++ return false;
++ }
++
++ external_to_relative_[pair.external] = pair.relative;
++ relative_to_external_[pair.relative] = pair.external;
++ return true;
++}
++
++absl::optional<pid_t> FlatpakPidMap::FindRelativeByExternal(pid_t external) {
++ return FindImpl(&external_to_relative_, external);
++}
++
++absl::optional<pid_t> FlatpakPidMap::FindExternalByRelative(pid_t relative) {
++ return FindImpl(&relative_to_external_, relative);
++}
++
++absl::optional<pid_t> FlatpakPidMap::DeleteByExternal(pid_t external) {
++ return DeleteImpl(&external_to_relative_, &relative_to_external_, external);
++}
++
++absl::optional<pid_t> FlatpakPidMap::DeleteByRelative(pid_t relative) {
++ return DeleteImpl(&relative_to_external_, &external_to_relative_, relative);
++}
++
++absl::optional<pid_t> FlatpakPidMap::FindImpl(base::flat_map<pid_t, pid_t>* map,
++ pid_t key) {
++ auto it = map->find(key);
++ return it != map->end() ? it->second : absl::optional<pid_t>();
++}
++
++absl::optional<pid_t> FlatpakPidMap::DeleteImpl(
++ base::flat_map<pid_t, pid_t>* map,
++ base::flat_map<pid_t, pid_t>* reversed,
++ pid_t key) {
++ auto it = map->find(key);
++ if (it == map->end()) {
++ return absl::optional<pid_t>();
++ }
++
++ pid_t value = it->second;
++ reversed->erase(value);
++ map->erase(it);
++ return value;
++}
++
++} // namespace sandbox
+diff --git a/sandbox/linux/services/flatpak_pid_map.h b/sandbox/linux/services/flatpak_pid_map.h
+new file mode 100644
+index 0000000000000..22799eb42f782
+--- /dev/null
++++ b/sandbox/linux/services/flatpak_pid_map.h
+@@ -0,0 +1,46 @@
++// Copyright 2020 The Chromium Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++
++#ifndef SANDBOX_LINUX_SERVICES_FLATPAK_PID_MAP_H_
++#define SANDBOX_LINUX_SERVICES_FLATPAK_PID_MAP_H_
++
++#include "base/containers/flat_map.h"
++#include "third_party/abseil-cpp/absl/types/optional.h"
++
++namespace sandbox {
++
++// A bidirectional map of external PIDs and relative PIDs for the Flatpak
++// sandbox. "External" PIDs are the PID values that Flatpak's Spawn API returns,
++// relative to the host system, and "relative" PIDs are the PIDs those processes
++// are known by from inside the sandbox.
++class FlatpakPidMap {
++ public:
++ struct PidPair {
++ pid_t external;
++ pid_t relative;
++ };
++
++ FlatpakPidMap() = default;
++
++ bool Insert(PidPair pair);
++
++ absl::optional<pid_t> FindRelativeByExternal(pid_t external);
++ absl::optional<pid_t> FindExternalByRelative(pid_t relative);
++
++ absl::optional<pid_t> DeleteByRelative(pid_t relative);
++ absl::optional<pid_t> DeleteByExternal(pid_t external);
++
++ private:
++ absl::optional<pid_t> FindImpl(base::flat_map<pid_t, pid_t>* map, pid_t key);
++ absl::optional<pid_t> DeleteImpl(base::flat_map<pid_t, pid_t>* map,
++ base::flat_map<pid_t, pid_t>* reversed,
++ pid_t key);
++
++ base::flat_map<pid_t, pid_t> external_to_relative_;
++ base::flat_map<pid_t, pid_t> relative_to_external_;
++}; // namespace sandbox
++
++} // namespace sandbox
++
++#endif
+diff --git a/sandbox/linux/services/flatpak_sandbox.cc b/sandbox/linux/services/flatpak_sandbox.cc
+new file mode 100644
+index 0000000000000..2a915a5b9fa11
+--- /dev/null
++++ b/sandbox/linux/services/flatpak_sandbox.cc
+@@ -0,0 +1,576 @@
++// Copyright 2019 The Chromium Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++
++#include "sandbox/linux/services/flatpak_sandbox.h"
++
++#include <signal.h>
++#include <sstream>
++#include <string>
++
++#include "base/files/file_path.h"
++#include "base/files/file_util.h"
++#include "base/functional/bind.h"
++#include "base/logging.h"
++#include "base/process/process_handle.h"
++#include "base/strings/string_number_conversions.h"
++#include "base/strings/string_util.h"
++#include "base/synchronization/lock.h"
++#include "base/threading/scoped_blocking_call.h"
++#include "base/threading/thread_restrictions.h"
++#include "dbus/bus.h"
++#include "dbus/message.h"
++#include "dbus/object_path.h"
++#include "dbus/object_proxy.h"
++#include "dbus/property.h"
++#include "sandbox/linux/services/flatpak_pid_map.h"
++
++namespace sandbox {
++
++namespace {
++const base::FilePath kFlatpakAppPath("/app");
++const base::FilePath kFlatpakInfoPath("/.flatpak-info");
++
++const char kFlatpakPortalServiceName[] = "org.freedesktop.portal.Flatpak";
++const char kFlatpakPortalObjectPath[] = "/org/freedesktop/portal/Flatpak";
++const char kFlatpakPortalInterfaceName[] = "org.freedesktop.portal.Flatpak";
++
++#ifndef NDEBUG
++const char kDisableFullFlatpakSandbox[] = "disable-full-flatpak-sandbox";
++#endif
++
++struct PortalProperties : dbus::PropertySet {
++ dbus::Property<uint32_t> version;
++ dbus::Property<uint32_t> supports;
++
++ enum FlatpakPortalSupports {
++ kFlatpakPortal_ExposePids = 1 << 0,
++ };
++
++ explicit PortalProperties(dbus::ObjectProxy* object_proxy)
++ : dbus::PropertySet(object_proxy, kFlatpakPortalInterfaceName, {}) {
++ RegisterProperty("version", &version);
++ RegisterProperty("supports", &supports);
++ }
++
++ ~PortalProperties() override = default;
++};
++
++void WriteStringAsByteArray(dbus::MessageWriter* writer,
++ const std::string& str) {
++ writer->AppendArrayOfBytes(base::make_span(
++ reinterpret_cast<const uint8_t*>(str.c_str()), str.size() + 1));
++}
++
++void WriteFdPairMap(dbus::MessageWriter* writer, int source_fd, int dest_fd) {
++ dbus::MessageWriter entry_writer(nullptr);
++ writer->OpenDictEntry(&entry_writer);
++
++ entry_writer.AppendUint32(dest_fd);
++ entry_writer.AppendFileDescriptor(source_fd);
++
++ writer->CloseContainer(&entry_writer);
++}
++
++} // namespace
++
++enum FlatpakSpawnFlags {
++ kFlatpakSpawn_ClearEnvironment = 1 << 0,
++ kFlatpakSpawn_Latest = 1 << 1,
++ kFlatpakSpawn_Sandbox = 1 << 2,
++ kFlatpakSpawn_NoNetwork = 1 << 3,
++ kFlatpakSpawn_WatchBus = 1 << 4,
++ kFlatpakSpawn_ExposePids = 1 << 5,
++ kFlatpakSpawn_NotifyStart = 1 << 6,
++};
++
++enum FlatpakSpawnSandboxFlags {
++ kFlatpakSpawnSandbox_ShareDisplay = 1 << 0,
++ kFlatpakSpawnSandbox_ShareSound = 1 << 1,
++ kFlatpakSpawnSandbox_ShareGpu = 1 << 2,
++ kFlatpakSpawnSandbox_ShareSessionBus = 1 << 3,
++ kFlatpakSpawnSandbox_ShareA11yBus = 1 << 4,
++};
++
++FlatpakSandbox::FlatpakSandbox()
++ : bus_thread_("FlatpakPortalBus"), process_info_cv_(&process_info_lock_) {}
++
++// static
++FlatpakSandbox* FlatpakSandbox::GetInstance() {
++ static base::NoDestructor<FlatpakSandbox> instance;
++ return instance.get();
++}
++
++FlatpakSandbox::SandboxLevel FlatpakSandbox::GetSandboxLevel() {
++ if (sandbox_level_) {
++ return *sandbox_level_;
++ }
++
++ // XXX: These operations shouldn't actually have a major blocking time,
++ // as .flatpak-info is on a tmpfs.
++ base::ScopedAllowBlocking scoped_allow_blocking;
++
++ if (!base::PathExists(kFlatpakInfoPath)) {
++ sandbox_level_ = SandboxLevel::kNone;
++ } else {
++ // chrome has an INI parser, but sandbox can't depend on anything inside
++ // chrome, so the .flatpak-info INI is manually checked for the sandbox
++ // option.
++
++ std::string contents;
++ CHECK(ReadFileToString(kFlatpakInfoPath, &contents));
++ DCHECK(!contents.empty());
++
++ std::istringstream iss(contents);
++ std::string line;
++ bool in_instance = false;
++ while (std::getline(iss, line)) {
++ if (!line.empty() && line[0] == '[') {
++ DCHECK(line.back() == ']');
++
++ if (line == "[Instance]") {
++ DCHECK(!in_instance);
++ in_instance = true;
++ } else if (in_instance) {
++ // Leaving the Instance section, sandbox=true can't come now.
++ break;
++ }
++ } else if (in_instance && line == "sandbox=true") {
++ sandbox_level_ = SandboxLevel::kRestricted;
++ break;
++ }
++ }
++
++ if (!sandbox_level_) {
++ sandbox_level_ = SandboxLevel::kFlatpak;
++ }
++ }
++
++#ifndef NDEBUG
++ if (sandbox_level_ == SandboxLevel::kFlatpak &&
++ base::CommandLine::ForCurrentProcess()->HasSwitch(
++ kDisableFullFlatpakSandbox)) {
++ sandbox_level_ = SandboxLevel::kRestricted;
++ }
++#endif
++
++ return *sandbox_level_;
++}
++
++bool FlatpakSandbox::IsPidSandboxed(base::ProcessId relative_pid) {
++ base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
++ base::BlockingType::MAY_BLOCK);
++
++ base::AutoLock locker(process_info_lock_);
++
++ return running_processes_.FindExternalByRelative(relative_pid).has_value();
++}
++
++base::Process FlatpakSandbox::LaunchProcess(
++ const base::CommandLine& cmdline,
++ const base::LaunchOptions& launch_options) {
++ base::ProcessId external_pid = Spawn(cmdline, launch_options);
++ if (external_pid == base::kNullProcessId) {
++ return base::Process();
++ }
++
++ base::ProcessId relative_pid = GetRelativePid(external_pid);
++ if (relative_pid == base::kNullProcessId) {
++ // Treat early stops as a launch failure.
++ return base::Process();
++ }
++
++ return base::Process(relative_pid);
++}
++
++bool FlatpakSandbox::Wait(base::ProcessId relative_pid, int* exit_code) {
++ base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
++ base::BlockingType::MAY_BLOCK);
++
++ base::AutoLock locker(process_info_lock_);
++
++ for (;;) {
++ if (running_processes_.FindExternalByRelative(relative_pid)) {
++ // Process is still running.
++ process_info_cv_.Wait();
++ continue;
++ }
++
++ auto it = exited_process_statuses_.find(relative_pid);
++ if (it == exited_process_statuses_.end()) {
++ // This should only happen if another caller had marked the exit status
++ // to be ignored. Treat it like waitpid returning ESRCH.
++ LOG(ERROR) << "PID " << relative_pid << " had no exit status";
++ return false;
++ }
++
++ if (exit_code) {
++ *exit_code = it->second;
++ }
++ exited_process_statuses_.erase(it);
++ return true;
++ }
++}
++
++void FlatpakSandbox::IgnoreExitStatus(base::ProcessId relative_pid) {
++ base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
++ base::BlockingType::MAY_BLOCK);
++
++ base::AutoLock locker(process_info_lock_);
++
++ CHECK(running_processes_.FindExternalByRelative(relative_pid));
++ ignore_status_.insert(relative_pid);
++}
++
++void FlatpakSandbox::StartBusThread() {
++ if (!bus_thread_.IsRunning()) {
++ base::Thread::Options options;
++ options.message_pump_type = base::MessagePumpType::IO;
++ CHECK(bus_thread_.StartWithOptions(std::move(options)));
++
++ bus_thread_.task_runner()->PostTask(
++ FROM_HERE, base::BindOnce(&FlatpakSandbox::InitializeBusThread,
++ base::Unretained(this)));
++ }
++}
++
++dbus::Bus* FlatpakSandbox::AcquireBusFromBusThread() {
++ // Note that destruction of the bus is not a concern, because once the
++ // thread dies its bus connection will be terminated anyway and the
++ // portal will notice.
++ static base::NoDestructor<scoped_refptr<dbus::Bus>> bus([] {
++ dbus::Bus::Options options;
++ options.bus_type = dbus::Bus::SESSION;
++ options.connection_type = dbus::Bus::PRIVATE;
++ options.dbus_task_runner = base::SequencedTaskRunner::GetCurrentDefault();
++
++ return base::MakeRefCounted<dbus::Bus>(options);
++ }());
++
++ return bus->get();
++}
++
++dbus::ObjectProxy* FlatpakSandbox::GetPortalObjectProxy() {
++ return AcquireBusFromBusThread()->GetObjectProxy(
++ kFlatpakPortalServiceName, dbus::ObjectPath(kFlatpakPortalObjectPath));
++}
++
++void FlatpakSandbox::InitializeBusThread() {
++ dbus::ObjectProxy* object_proxy = GetPortalObjectProxy();
++
++ PortalProperties properties(object_proxy);
++ properties.ConnectSignals();
++
++ CHECK(properties.GetAndBlock(&properties.version))
++ << "Failed to get portal version";
++ CHECK(properties.GetAndBlock(&properties.supports))
++ << "Failed to get portal supports";
++
++ if (properties.version.value() < 4) {
++ LOG(FATAL) << "Your Flatpak version is too old, please update it";
++ }
++
++ if (!(properties.supports.value() &
++ PortalProperties::kFlatpakPortal_ExposePids)) {
++ LOG(FATAL) << "Your Flatpak installation is setuid, which is not supported";
++ }
++
++ object_proxy->ConnectToSignal(
++ kFlatpakPortalInterfaceName, "SpawnStarted",
++ base::BindRepeating(&FlatpakSandbox::OnSpawnStartedSignal,
++ base::Unretained(this)),
++ base::BindOnce(&FlatpakSandbox::OnSignalConnected,
++ base::Unretained(this)));
++
++ object_proxy->ConnectToSignal(
++ kFlatpakPortalInterfaceName, "SpawnExited",
++ base::BindRepeating(&FlatpakSandbox::OnSpawnExitedSignal,
++ base::Unretained(this)),
++ base::BindOnce(&FlatpakSandbox::OnSignalConnected,
++ base::Unretained(this)));
++}
++
++void FlatpakSandbox::OnSignalConnected(const std::string& interface,
++ const std::string& signal,
++ bool connected) {
++ // It's not safe to spawn processes without being able to track their deaths.
++ CHECK(connected) << "Failed to connect to signal " << signal;
++}
++
++void FlatpakSandbox::OnSpawnStartedSignal(dbus::Signal* signal) {
++ dbus::MessageReader reader(signal);
++ uint32_t external_pid, relative_pid;
++
++ if (!reader.PopUint32(&external_pid) || !reader.PopUint32(&relative_pid)) {
++ LOG(ERROR) << "Invalid SpawnStarted signal";
++ return;
++ }
++
++ VLOG(1) << "Received SpawnStarted: " << external_pid << ' ' << relative_pid;
++
++ base::AutoLock locker(process_info_lock_);
++
++ auto it = unmapped_processes_.find(external_pid);
++ if (it == unmapped_processes_.end()) {
++ LOG(ERROR) << "Process " << external_pid
++ << " is already dead or not tracked";
++ return;
++ }
++
++ unmapped_processes_.erase(it);
++
++ // Don't try to map them if the process died too quickly (which is the cause
++ // of relative_pid == 0).
++ if (relative_pid != 0) {
++ FlatpakPidMap::PidPair pair;
++ pair.external = external_pid;
++ pair.relative = relative_pid;
++ running_processes_.Insert(pair);
++ }
++
++ process_info_cv_.Broadcast();
++}
++
++void FlatpakSandbox::OnSpawnExitedSignal(dbus::Signal* signal) {
++ dbus::MessageReader reader(signal);
++ uint32_t external_pid, exit_status;
++
++ if (!reader.PopUint32(&external_pid) || !reader.PopUint32(&exit_status)) {
++ LOG(ERROR) << "Invalid SpawnExited signal";
++ return;
++ }
++
++ VLOG(1) << "Received SpawnExited: " << external_pid << ' ' << exit_status;
++
++ base::AutoLock locker(process_info_lock_);
++
++ auto relative_pid = running_processes_.DeleteByExternal(external_pid);
++ // If this isn't found, it likely never ran long enough for SpawnStarted to be
++ // emitted, so we never bother saving the exit status.
++ if (relative_pid) {
++ auto ignore_it = ignore_status_.find(*relative_pid);
++ if (ignore_it != ignore_status_.end()) {
++ // Make sure the exit status is not set.
++ relative_pid.reset();
++ ignore_status_.erase(ignore_it);
++ }
++ }
++
++ if (relative_pid) {
++ exited_process_statuses_[*relative_pid] = exit_status;
++ }
++
++ process_info_cv_.Broadcast();
++}
++
++base::ProcessId FlatpakSandbox::Spawn(
++ const base::CommandLine& cmdline,
++ const base::LaunchOptions& launch_options) {
++ base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
++ base::BlockingType::MAY_BLOCK);
++ base::ScopedAllowBaseSyncPrimitives allow_wait;
++
++ StartBusThread();
++
++ VLOG(1) << "Running via Flatpak: " << cmdline.GetCommandLineString();
++
++ DCHECK(GetSandboxLevel() != SandboxLevel::kNone);
++
++ // These options are not supported with the Flatpak sandbox.
++ DCHECK(launch_options.clone_flags == 0);
++ DCHECK(!launch_options.wait);
++ DCHECK(!launch_options.allow_new_privs);
++ DCHECK(launch_options.real_path.empty());
++ DCHECK(launch_options.pre_exec_delegate == nullptr);
++ DCHECK(launch_options.maximize_rlimits == nullptr);
++
++ base::ProcessId external_pid = base::kNullProcessId;
++ base::WaitableEvent event;
++
++ bus_thread_.task_runner()->PostTask(
++ FROM_HERE,
++ base::BindOnce(&FlatpakSandbox::SpawnOnBusThread, base::Unretained(this),
++ base::Unretained(&external_pid), base::Unretained(&event),
++ cmdline, launch_options));
++ event.Wait();
++
++ return external_pid;
++}
++
++void FlatpakSandbox::SpawnOnBusThread(
++ base::ProcessId* out_external_pid,
++ base::WaitableEvent* event,
++ const base::CommandLine& cmdline,
++ const base::LaunchOptions& launch_options) {
++ dbus::ObjectProxy* object_proxy = GetPortalObjectProxy();
++ dbus::MethodCall method_call(kFlatpakPortalInterfaceName, "Spawn");
++ dbus::MessageWriter writer(&method_call);
++
++ const base::FilePath& current_directory =
++ !launch_options.current_directory.empty()
++ ? launch_options.current_directory
++ // Change to /app since it's guaranteed to always be present in
++ // the sandbox.
++ : kFlatpakAppPath;
++ WriteStringAsByteArray(&writer, current_directory.value());
++
++ dbus::MessageWriter argv_writer(nullptr);
++ writer.OpenArray("ay", &argv_writer);
++
++ for (const std::string& arg : cmdline.argv()) {
++ WriteStringAsByteArray(&argv_writer, arg);
++ }
++
++#ifndef NDEBUG
++ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
++ kDisableFullFlatpakSandbox)) {
++ std::string arg = "--";
++ arg += kDisableFullFlatpakSandbox;
++ WriteStringAsByteArray(&argv_writer, arg);
++ }
++#endif
++
++ writer.CloseContainer(&argv_writer);
++
++ dbus::MessageWriter fds_writer(nullptr);
++ writer.OpenArray("{uh}", &fds_writer);
++
++ WriteFdPairMap(&fds_writer, STDIN_FILENO, STDIN_FILENO);
++ WriteFdPairMap(&fds_writer, STDOUT_FILENO, STDOUT_FILENO);
++ WriteFdPairMap(&fds_writer, STDERR_FILENO, STDERR_FILENO);
++
++ for (const auto& pair : launch_options.fds_to_remap) {
++ WriteFdPairMap(&fds_writer, pair.first, pair.second);
++ }
++
++ writer.CloseContainer(&fds_writer);
++
++ dbus::MessageWriter env_writer(nullptr);
++ writer.OpenArray("{ss}", &env_writer);
++
++ for (const auto& pair : launch_options.environment) {
++ dbus::MessageWriter entry_writer(nullptr);
++ env_writer.OpenDictEntry(&entry_writer);
++
++ entry_writer.AppendString(pair.first);
++ entry_writer.AppendString(pair.second);
++
++ env_writer.CloseContainer(&entry_writer);
++ }
++
++ writer.CloseContainer(&env_writer);
++
++ int spawn_flags = kFlatpakSpawn_Sandbox | kFlatpakSpawn_ExposePids |
++ kFlatpakSpawn_NotifyStart;
++ int sandbox_flags = 0;
++
++#ifndef NDEBUG
++ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
++ kDisableFullFlatpakSandbox)) {
++ spawn_flags &= ~kFlatpakSpawn_Sandbox;
++ }
++#else
++#endif
++
++ if (launch_options.clear_environment) {
++ spawn_flags |= kFlatpakSpawn_ClearEnvironment;
++ }
++
++ if (launch_options.kill_on_parent_death) {
++ spawn_flags |= kFlatpakSpawn_WatchBus;
++ }
++
++ writer.AppendUint32(spawn_flags);
++
++ dbus::MessageWriter options_writer(nullptr);
++ writer.OpenArray("{sv}", &options_writer);
++
++ if (sandbox_flags != 0) {
++ dbus::MessageWriter entry_writer(nullptr);
++ options_writer.OpenDictEntry(&entry_writer);
++
++ entry_writer.AppendString("sandbox-flags");
++
++ dbus::MessageWriter variant_writer(nullptr);
++ entry_writer.OpenVariant("u", &variant_writer);
++
++ variant_writer.AppendUint32(sandbox_flags);
++
++ entry_writer.CloseContainer(&variant_writer);
++ options_writer.CloseContainer(&entry_writer);
++ }
++
++ writer.CloseContainer(&options_writer);
++
++ object_proxy->CallMethodWithErrorResponse(
++ &method_call, dbus::ObjectProxy::TIMEOUT_INFINITE,
++ base::BindOnce(&FlatpakSandbox::OnSpawnResponse, base::Unretained(this),
++ base::Unretained(out_external_pid),
++ base::Unretained(event)));
++}
++
++void FlatpakSandbox::OnSpawnResponse(base::ProcessId* out_external_pid,
++ base::WaitableEvent* event,
++ dbus::Response* response,
++ dbus::ErrorResponse* error_response) {
++ if (response) {
++ dbus::MessageReader reader(response);
++ uint32_t external_pid;
++ if (!reader.PopUint32(&external_pid)) {
++ LOG(ERROR) << "Invalid Spawn() response";
++ } else {
++ VLOG(1) << "Spawn() returned PID " << external_pid;
++ if (out_external_pid != nullptr) {
++ *out_external_pid = external_pid;
++ }
++
++ base::AutoLock locker(process_info_lock_);
++ unmapped_processes_.insert(external_pid);
++ }
++ } else if (error_response) {
++ std::string error_name = error_response->GetErrorName();
++ std::string error_message;
++ dbus::MessageReader reader(error_response);
++ reader.PopString(&error_message);
++
++ LOG(ERROR) << "Error calling Spawn(): " << error_name << ": "
++ << error_message;
++ } else {
++ LOG(ERROR) << "Unknown error occurred calling Spawn()";
++ }
++
++ if (event != nullptr) {
++ event->Signal();
++ }
++}
++
++base::ProcessId FlatpakSandbox::GetRelativePid(base::ProcessId external_pid) {
++ base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
++ base::BlockingType::MAY_BLOCK);
++ base::ScopedAllowBaseSyncPrimitives allow_wait;
++
++ base::AutoLock locker(process_info_lock_);
++
++ for (;;) {
++ auto unmapped_it = unmapped_processes_.find(external_pid);
++ if (unmapped_it != unmapped_processes_.end()) {
++ // No relative PID is known yet.
++ VLOG(1) << "Waiting for " << external_pid;
++ process_info_cv_.Wait();
++ continue;
++ }
++
++ auto relative_pid = running_processes_.FindRelativeByExternal(external_pid);
++ if (!relative_pid) {
++ exited_process_statuses_.erase(external_pid);
++
++ LOG(INFO) << "Already died: " << external_pid;
++ return base::kNullProcessId;
++ }
++
++ VLOG(1) << "Got " << external_pid << " => " << *relative_pid;
++ return *relative_pid;
++ }
++}
++
++} // namespace sandbox
+diff --git a/sandbox/linux/services/flatpak_sandbox.h b/sandbox/linux/services/flatpak_sandbox.h
+new file mode 100644
+index 0000000000000..167bbc85945ad
+--- /dev/null
++++ b/sandbox/linux/services/flatpak_sandbox.h
+@@ -0,0 +1,118 @@
++// Copyright 2019 The Chromium Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++
++#ifndef SANDBOX_LINUX_SERVICES_FLATPAK_SANDBOX_H_
++#define SANDBOX_LINUX_SERVICES_FLATPAK_SANDBOX_H_
++
++#include "base/command_line.h"
++#include "base/compiler_specific.h"
++#include "base/containers/flat_map.h"
++#include "base/containers/flat_set.h"
++#include "base/no_destructor.h"
++#include "base/process/kill.h"
++#include "base/process/launch.h"
++#include "base/process/process_handle.h"
++#include "base/synchronization/condition_variable.h"
++#include "base/synchronization/lock.h"
++#include "base/synchronization/waitable_event.h"
++#include "base/threading/thread.h"
++#include "dbus/bus.h"
++#include "dbus/message.h"
++#include "sandbox/linux/services/flatpak_pid_map.h"
++#include "sandbox/sandbox_export.h"
++#include "third_party/abseil-cpp/absl/types/optional.h"
++
++namespace sandbox {
++
++// Manages the state of and access to the Flatpak sandbox.
++// Note that there is a distinction between external and internal PIDs:
++// - External PIDs are the PIDs relative to the world outside the sandbox.
++// - Internal PIDs are the PIDs relative to the current PID namespace.
++// Flatpak's sandbox APIs work primarily with external PIDs, and an
++// internal PID must be retrieved from the SpawnStarted signal before
++// it is known inside the sandbox's PID namespace.
++class SANDBOX_EXPORT FlatpakSandbox {
++ public:
++ static FlatpakSandbox* GetInstance();
++
++ // Represents the level of sandboxing inside a Flatpak. kNone means this is
++ // not a Flatpak, kFlatpak means it's inside a Flatpak sandbox, and
++ // kRestricted means that this is inside a nested Flatpak sandbox with most
++ // permissions revoked.
++ enum class SandboxLevel { kNone, kFlatpak, kRestricted };
++
++ // Get the current level of sandboxing in this Flatpak.
++ SandboxLevel GetSandboxLevel();
++
++ // Returns whether or not the given PID was spawned via the Flatpak sandbox.
++ bool IsPidSandboxed(base::ProcessId relative_pid);
++
++ // Launch the given process inside of a Flatpak sandbox. If allow_x11 is true,
++ // then the process will be given access to the host's X11 display. On
++ // failure, returns kNullProcessId. Note that the return value is the PID
++ // relative to the host i.e. outside the sandbox, to get the internal one call
++ // GetRelativePid. This is the reason why a vanilla ProcessId is returned
++ // rather than a base::Process instance.
++ base::Process LaunchProcess(const base::CommandLine& cmdline,
++ const base::LaunchOptions& launch_options);
++
++ // Indefinitely waits for the given process and fills the exit code pointer
++ // if given and non-null. Returns false on wait failure.
++ bool Wait(base::ProcessId relative_pid, int* exit_code);
++
++ // Skips storing the exit status of the given PID.
++ void IgnoreExitStatus(base::ProcessId relative_pid);
++
++ private:
++ friend class base::NoDestructor<FlatpakSandbox>;
++
++ FlatpakSandbox();
++ FlatpakSandbox(const FlatpakSandbox&) = delete;
++ FlatpakSandbox(FlatpakSandbox&&) = delete;
++ ~FlatpakSandbox();
++
++ void StartBusThread();
++ dbus::Bus* AcquireBusFromBusThread();
++ dbus::ObjectProxy* GetPortalObjectProxy();
++
++ void InitializeBusThread();
++ void OnSignalConnected(const std::string& interface,
++ const std::string& signal,
++ bool connected);
++ void OnSpawnStartedSignal(dbus::Signal* signal);
++ void OnSpawnExitedSignal(dbus::Signal* signal);
++
++ base::ProcessId Spawn(const base::CommandLine& cmdline,
++ const base::LaunchOptions& launch_options);
++ void SpawnOnBusThread(base::ProcessId* out_external_pid,
++ base::WaitableEvent* event,
++ const base::CommandLine& cmdline,
++ const base::LaunchOptions& launch_options);
++ void OnSpawnResponse(base::ProcessId* out_external_pid,
++ base::WaitableEvent* event,
++ dbus::Response* response,
++ dbus::ErrorResponse* error_response);
++
++ base::ProcessId GetRelativePid(base::ProcessId external_pid);
++
++ absl::optional<SandboxLevel> sandbox_level_;
++ base::Thread bus_thread_;
++
++ base::Lock process_info_lock_;
++ // Note that broadcast is used in the source, because in general
++ // very few threads will be contending for the lock.
++ base::ConditionVariable process_info_cv_;
++ // Set of processes that have no associated relative PID yet.
++ base::flat_set<base::ProcessId> unmapped_processes_;
++ // Map of running processes.
++ FlatpakPidMap running_processes_;
++ // Map of a relative process ID that has exited to its waitpid status.
++ std::map<base::ProcessId, int> exited_process_statuses_;
++ // Relative process IDs that should have their statuses ignored on exit.
++ std::set<base::ProcessId> ignore_status_;
++};
++
++} // namespace sandbox
++
++#endif // SANDBOX_LINUX_SERVICES_FLATPAK_SANDBOX_H_
+diff --git a/sandbox/policy/BUILD.gn b/sandbox/policy/BUILD.gn
+index 4fe53b047b9aa..794e1ad1805d8 100644
+--- a/sandbox/policy/BUILD.gn
++++ b/sandbox/policy/BUILD.gn
+@@ -129,6 +129,9 @@ component("policy") {
+ "//sandbox/linux:suid_sandbox_client",
+ ]
+ }
++ if (is_linux) {
++ public_deps += [ "//sandbox/linux:sandbox_services" ]
++ }
+ if (is_chromeos_ash) {
+ sources += [
+ "linux/bpf_ime_policy_linux.cc",
+diff --git a/sandbox/policy/linux/sandbox_linux.cc b/sandbox/policy/linux/sandbox_linux.cc
+index c7313416e6183..0cb8043f0ac72 100644
+--- a/sandbox/policy/linux/sandbox_linux.cc
++++ b/sandbox/policy/linux/sandbox_linux.cc
+@@ -37,6 +37,7 @@
+ #include "sandbox/constants.h"
+ #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
+ #include "sandbox/linux/services/credentials.h"
++#include "sandbox/linux/services/flatpak_sandbox.h"
+ #include "sandbox/linux/services/libc_interceptor.h"
+ #include "sandbox/linux/services/namespace_sandbox.h"
+ #include "sandbox/linux/services/proc_util.h"
+@@ -236,6 +237,9 @@ void SandboxLinux::PreinitializeSandbox() {
+ const int yama_status = Yama::GetStatus();
+ yama_is_enforcing_ = (yama_status & Yama::STATUS_PRESENT) &&
+ (yama_status & Yama::STATUS_ENFORCING);
++
++ flatpak_sandbox_level_ =
++ sandbox::FlatpakSandbox::GetInstance()->GetSandboxLevel();
+ pre_initialized_ = true;
+ }
+
+@@ -274,6 +278,10 @@ int SandboxLinux::GetStatus() {
+ sandbox_status_flags_ |= kPIDNS;
+ if (NamespaceSandbox::InNewNetNamespace())
+ sandbox_status_flags_ |= kNetNS;
++ } else if (flatpak_sandbox_level_ ==
++ sandbox::FlatpakSandbox::SandboxLevel::kRestricted) {
++ // Flatpak sandboxes always use new namespaces.
++ sandbox_status_flags_ |= kFlatpak | kPIDNS | kNetNS;
+ }
+
+ // We report whether the sandbox will be activated when renderers, workers
+diff --git a/sandbox/policy/linux/sandbox_linux.h b/sandbox/policy/linux/sandbox_linux.h
+index 0e4f78b9e6cb7..91b638d8a96e0 100644
+--- a/sandbox/policy/linux/sandbox_linux.h
++++ b/sandbox/policy/linux/sandbox_linux.h
+@@ -13,6 +13,7 @@
+ #include "base/memory/raw_ptr.h"
+ #include "base/posix/global_descriptors.h"
+ #include "base/sanitizer_buildflags.h"
++#include "sandbox/linux/services/flatpak_sandbox.h"
+ #include "sandbox/linux/syscall_broker/broker_command.h"
+ #include "sandbox/linux/syscall_broker/broker_file_permission.h"
+ #include "sandbox/policy/export.h"
+@@ -91,6 +92,9 @@ class SANDBOX_POLICY_EXPORT SandboxLinux {
+ // User namespace sandbox active.
+ kUserNS = 1 << 6,
+
++ // Flatpak sandbox active.
++ kFlatpak = 1 << 7,
++
+ // A flag that denotes an invalid sandbox status.
+ kInvalid = 1 << 31,
+ };
+@@ -292,6 +296,10 @@ class SANDBOX_POLICY_EXPORT SandboxLinux {
+ bool seccomp_bpf_with_tsync_supported_; // Accurate if pre_initialized_.
+ bool yama_is_enforcing_; // Accurate if pre_initialized_.
+ bool initialize_sandbox_ran_; // InitializeSandbox() was called.
++ // Accurate if pre_initialized_, used to save the state of the Flatpak
++ // sandbox, as once we're in the BPF sandbox any attempts to check the Flatpak
++ // state will cause EPERM errors.
++ sandbox::FlatpakSandbox::SandboxLevel flatpak_sandbox_level_;
+ std::unique_ptr<SetuidSandboxClient> setuid_sandbox_client_;
+ #if BUILDFLAG(USING_SANITIZER)
+ std::unique_ptr<__sanitizer_sandbox_arguments> sanitizer_args_;
+diff --git a/services/service_manager/service_process_launcher.cc b/services/service_manager/service_process_launcher.cc
+index e24a262fe90d5..c20fdbd88a1a6 100644
+--- a/services/service_manager/service_process_launcher.cc
++++ b/services/service_manager/service_process_launcher.cc
+@@ -41,6 +41,7 @@
+ #endif
+
+ #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
++#include "sandbox/linux/services/flatpak_sandbox.h"
+ #include "sandbox/linux/services/namespace_sandbox.h"
+ #endif
+
+@@ -286,8 +287,15 @@ void ServiceProcessLauncher::ProcessState::StopInBackground() {
+ return;
+
+ int rv = -1;
+- LOG_IF(ERROR, !child_process_.WaitForExit(&rv))
+- << "Failed to wait for child process";
++ bool success = false;
++ auto* flatpak_sandbox = sandbox::FlatpakSandbox::GetInstance();
++ if (flatpak_sandbox->IsPidSandboxed(child_process_.Pid())) {
++ success = flatpak_sandbox->Wait(child_process_.Pid(), &rv);
++ } else {
++ success = child_process_.WaitForExit(&rv);
++ }
++ LOG_IF(ERROR, success) << "Failed to wait for child process";
++
+ child_process_.Close();
+ }
+
+--
+2.46.1
+
diff --git a/flatpak-Adjust-paths-for-the-sandbox.patch b/flatpak-Adjust-paths-for-the-sandbox.patch
new file mode 100644
index 0000000..3b1863d
--- /dev/null
+++ b/flatpak-Adjust-paths-for-the-sandbox.patch
@@ -0,0 +1,86 @@
+From 997c9dc4160c468f26acb851eb65408f41e2a091 Mon Sep 17 00:00:00 2001
+From: Ryan Gonzalez <rymg19@gmail.com>
+Date: Tue, 25 Aug 2020 19:26:07 -0500
+Subject: [PATCH] flatpak: Adjust paths for the sandbox
+
+---
+ chrome/common/BUILD.gn | 4 ++++
+ chrome/common/chrome_paths.cc | 26 +++++++++++++++++++++++++-
+ 2 files changed, 29 insertions(+), 1 deletion(-)
+
+diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
+index 76cf6a5985990..4044c87b656c4 100644
+--- a/chrome/common/BUILD.gn
++++ b/chrome/common/BUILD.gn
+@@ -642,6 +642,10 @@ static_library("constants") {
+ "//third_party/widevine/cdm:headers",
+ ]
+ }
++
++ if (is_linux) {
++ deps += [ "//sandbox/linux:sandbox_services" ]
++ }
+ }
+
+ # Use a static library here because many test binaries depend on this but don't
+diff --git a/chrome/common/chrome_paths.cc b/chrome/common/chrome_paths.cc
+index ec09803ffabcf..ecbc300b99e1d 100644
+--- a/chrome/common/chrome_paths.cc
++++ b/chrome/common/chrome_paths.cc
+@@ -38,6 +38,10 @@
+ #include "base/win/registry.h"
+ #endif
+
++#if BUILDFLAG(IS_LINUX)
++#include "sandbox/linux/services/flatpak_sandbox.h"
++#endif
++
+ #if BUILDFLAG(ENABLE_WIDEVINE)
+ #include "third_party/widevine/cdm/widevine_cdm_common.h" // nogncheck
+ #endif
+@@ -537,6 +541,14 @@ bool PathProvider(int key, base::FilePath* result) {
+ break;
+ #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_OPENBSD)
+ case chrome::DIR_POLICY_FILES: {
++#if defined(OS_LINUX)
++ if (sandbox::FlatpakSandbox::GetInstance()->GetSandboxLevel() >
++ sandbox::FlatpakSandbox::SandboxLevel::kNone) {
++ cur = base::FilePath(
++ FILE_PATH_LITERAL("/app/chromium/extensions/policies"));
++ break;
++ }
++#endif
+ cur = base::FilePath(policy::kPolicyPath);
+ break;
+ }
+@@ -557,7 +569,13 @@ bool PathProvider(int key, base::FilePath* result) {
+ #endif
+ #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
+ case chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS: {
+- cur = base::FilePath(kFilepathSinglePrefExtensions);
++ if (sandbox::FlatpakSandbox::GetInstance()->GetSandboxLevel() >
++ sandbox::FlatpakSandbox::SandboxLevel::kNone) {
++ cur = base::FilePath(
++ FILE_PATH_LITERAL("/app/chromium/extensions/extensions"));
++ } else {
++ cur = base::FilePath(kFilepathSinglePrefExtensions);
++ }
+ break;
+ }
+ #endif
+@@ -604,6 +622,12 @@ bool PathProvider(int key, base::FilePath* result) {
+ "/Library/Application Support/Chromium/NativeMessagingHosts"));
+ #endif
+ #else // BUILDFLAG(IS_MAC)
++ if (sandbox::FlatpakSandbox::GetInstance()->GetSandboxLevel() >
++ sandbox::FlatpakSandbox::SandboxLevel::kNone) {
++ cur = base::FilePath(FILE_PATH_LITERAL(
++ "/app/chromium/extensions/native-messaging-hosts"));
++ break;
++ }
+ #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+ cur = base::FilePath(
+ FILE_PATH_LITERAL("/etc/opt/chrome/native-messaging-hosts"));
+--
+2.46.1
+
diff --git a/flatpak-Expose-Widevine-into-the-sandbox.patch b/flatpak-Expose-Widevine-into-the-sandbox.patch
new file mode 100644
index 0000000..b6f953d
--- /dev/null
+++ b/flatpak-Expose-Widevine-into-the-sandbox.patch
@@ -0,0 +1,326 @@
+From 0446b3432c90bbab893c7bde22a5e664e14753af Mon Sep 17 00:00:00 2001
+From: Ryan Gonzalez <rymg19@gmail.com>
+Date: Tue, 17 Nov 2020 13:00:39 -0600
+Subject: [PATCH] flatpak: Expose Widevine into the sandbox
+
+---
+ .../zygote_host/zygote_host_impl_linux.cc | 54 +++++++++++++-
+ sandbox/linux/services/flatpak_sandbox.cc | 74 ++++++++++++++-----
+ sandbox/linux/services/flatpak_sandbox.h | 27 ++++++-
+ 3 files changed, 131 insertions(+), 24 deletions(-)
+
+diff --git a/content/browser/zygote_host/zygote_host_impl_linux.cc b/content/browser/zygote_host/zygote_host_impl_linux.cc
+index 1703fb6ade044..3e8eb87981230 100644
+--- a/content/browser/zygote_host/zygote_host_impl_linux.cc
++++ b/content/browser/zygote_host/zygote_host_impl_linux.cc
+@@ -9,7 +9,10 @@
+ #include <sys/types.h>
+
+ #include "base/files/file_enumerator.h"
++#include "base/files/file_util.h"
+ #include "base/logging.h"
++#include "base/nix/xdg_util.h"
++#include "base/path_service.h"
+ #include "base/posix/unix_domain_socket.h"
+ #include "base/process/kill.h"
+ #include "base/process/launch.h"
+@@ -18,9 +21,12 @@
+ #include "base/types/fixed_array.h"
+ #include "build/build_config.h"
+ #include "build/chromeos_buildflags.h"
++#include "chrome/common/chrome_paths.h" // nogncheck
+ #include "content/common/zygote/zygote_commands_linux.h"
+ #include "content/common/zygote/zygote_communication_linux.h"
+ #include "content/common/zygote/zygote_handle_impl_linux.h"
++#include "content/public/common/cdm_info.h"
++#include "content/public/common/content_client.h"
+ #include "content/public/common/zygote/zygote_handle.h"
+ #include "sandbox/linux/services/credentials.h"
+ #include "sandbox/linux/services/flatpak_sandbox.h"
+@@ -29,6 +35,7 @@
+ #include "sandbox/linux/suid/common/sandbox.h"
+ #include "sandbox/policy/linux/sandbox_linux.h"
+ #include "sandbox/policy/switches.h"
++#include "third_party/widevine/cdm/buildflags.h" // nogncheck
+
+ #if BUILDFLAG(IS_CHROMEOS)
+ #include "content/common/zygote/zygote_communication_linux.h"
+@@ -193,8 +200,51 @@ pid_t ZygoteHostImpl::LaunchZygote(
+ if (is_sandboxed_zygote && use_namespace_sandbox_) {
+ process = sandbox::NamespaceSandbox::LaunchProcess(*cmd_line, options);
+ } else if (is_sandboxed_zygote && use_flatpak_sandbox_) {
+- process = sandbox::FlatpakSandbox::GetInstance()->LaunchProcess(*cmd_line,
+- options);
++ sandbox::FlatpakSandbox::SpawnOptions spawn_options;
++
++#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
++ // Expose the CDM paths into the sandbox. This is similar to PreSandboxInit
++ // in content_main_runner_impl.cc.
++ std::vector<CdmInfo> cdms;
++ GetContentClient()->AddContentDecryptionModules(&cdms, nullptr);
++ for (const auto& cdm : cdms) {
++ if (!spawn_options.ExposePathRo(cdm.path)) {
++ LOG(ERROR) << "Failed to expose CDM module";
++ }
++ }
++#endif
++
++#if BUILDFLAG(ENABLE_WIDEVINE_CDM_COMPONENT)
++ // Make sure we also expose the full Widevine CDM folder so it can be
++ // detected.
++ // TODO: Remove the explicit dependencies on chrome::.
++ base::FilePath widevine_cdm_path;
++ if (!base::PathService::Get(chrome::DIR_COMPONENT_UPDATED_WIDEVINE_CDM,
++ &widevine_cdm_path)) {
++ LOG(ERROR) << "Failed to get Widevine CDM folder for sandbox forwarding";
++ }
++
++ LOG(INFO) << "Widevine CDM path IS: " << widevine_cdm_path;
++
++ if (!widevine_cdm_path.empty() && base::PathExists(widevine_cdm_path)) {
++ if (!spawn_options.ExposePathRo(widevine_cdm_path)) {
++ LOG(ERROR) << "Failed to expose updated Widevine CDM path";
++ }
++ }
++
++ // The Widevine data is found relative to $XDG_CONFIG_HOME, which is not set
++ // by default when running a sandboxed process.
++ auto env = base::Environment::Create();
++ base::FilePath xdgConfigHome = base::nix::GetXDGDirectory(
++ env.get(), base::nix::kXdgConfigHomeEnvVar, nullptr);
++ if (!xdgConfigHome.empty()) {
++ options.environment[base::nix::kXdgConfigHomeEnvVar] =
++ xdgConfigHome.value();
++ }
++#endif
++
++ process = sandbox::FlatpakSandbox::GetInstance()->LaunchProcess(
++ *cmd_line, options, spawn_options);
+ } else {
+ process = base::LaunchProcess(*cmd_line, options);
+ }
+diff --git a/sandbox/linux/services/flatpak_sandbox.cc b/sandbox/linux/services/flatpak_sandbox.cc
+index 2a915a5b9fa11..ed8d4c0556f63 100644
+--- a/sandbox/linux/services/flatpak_sandbox.cc
++++ b/sandbox/linux/services/flatpak_sandbox.cc
+@@ -4,6 +4,7 @@
+
+ #include "sandbox/linux/services/flatpak_sandbox.h"
+
++#include <fcntl.h>
+ #include <signal.h>
+ #include <sstream>
+ #include <string>
+@@ -92,6 +93,18 @@ enum FlatpakSpawnSandboxFlags {
+ kFlatpakSpawnSandbox_ShareA11yBus = 1 << 4,
+ };
+
++bool FlatpakSandbox::SpawnOptions::ExposePathRo(base::FilePath path) {
++ base::ScopedFD fd(
++ HANDLE_EINTR(open(path.value().c_str(), O_PATH | O_NOFOLLOW)));
++ if (!fd.is_valid()) {
++ PLOG(ERROR) << "Failed to expose path " << path;
++ return false;
++ }
++
++ sandbox_expose_ro.push_back(std::move(fd));
++ return true;
++}
++
+ FlatpakSandbox::FlatpakSandbox()
+ : bus_thread_("FlatpakPortalBus"), process_info_cv_(&process_info_lock_) {}
+
+@@ -168,8 +181,9 @@ bool FlatpakSandbox::IsPidSandboxed(base::ProcessId relative_pid) {
+
+ base::Process FlatpakSandbox::LaunchProcess(
+ const base::CommandLine& cmdline,
+- const base::LaunchOptions& launch_options) {
+- base::ProcessId external_pid = Spawn(cmdline, launch_options);
++ const base::LaunchOptions& launch_options,
++ const SpawnOptions& spawn_options /*= {}*/) {
++ base::ProcessId external_pid = Spawn(cmdline, launch_options, spawn_options);
+ if (external_pid == base::kNullProcessId) {
+ return base::Process();
+ }
+@@ -363,9 +377,9 @@ void FlatpakSandbox::OnSpawnExitedSignal(dbus::Signal* signal) {
+ process_info_cv_.Broadcast();
+ }
+
+-base::ProcessId FlatpakSandbox::Spawn(
+- const base::CommandLine& cmdline,
+- const base::LaunchOptions& launch_options) {
++base::ProcessId FlatpakSandbox::Spawn(const base::CommandLine& cmdline,
++ const base::LaunchOptions& launch_options,
++ const SpawnOptions& spawn_options) {
+ base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
+ base::BlockingType::MAY_BLOCK);
+ base::ScopedAllowBaseSyncPrimitives allow_wait;
+@@ -391,24 +405,26 @@ base::ProcessId FlatpakSandbox::Spawn(
+ FROM_HERE,
+ base::BindOnce(&FlatpakSandbox::SpawnOnBusThread, base::Unretained(this),
+ base::Unretained(&external_pid), base::Unretained(&event),
+- cmdline, launch_options));
++ base::Unretained(&cmdline),
++ base::Unretained(&launch_options),
++ base::Unretained(&spawn_options)));
+ event.Wait();
+
+ return external_pid;
+ }
+
+-void FlatpakSandbox::SpawnOnBusThread(
+- base::ProcessId* out_external_pid,
+- base::WaitableEvent* event,
+- const base::CommandLine& cmdline,
+- const base::LaunchOptions& launch_options) {
++void FlatpakSandbox::SpawnOnBusThread(base::ProcessId* out_external_pid,
++ base::WaitableEvent* event,
++ const base::CommandLine* cmdline,
++ const base::LaunchOptions* launch_options,
++ const SpawnOptions* spawn_options) {
+ dbus::ObjectProxy* object_proxy = GetPortalObjectProxy();
+ dbus::MethodCall method_call(kFlatpakPortalInterfaceName, "Spawn");
+ dbus::MessageWriter writer(&method_call);
+
+ const base::FilePath& current_directory =
+- !launch_options.current_directory.empty()
+- ? launch_options.current_directory
++ !launch_options->current_directory.empty()
++ ? launch_options->current_directory
+ // Change to /app since it's guaranteed to always be present in
+ // the sandbox.
+ : kFlatpakAppPath;
+@@ -417,7 +433,7 @@ void FlatpakSandbox::SpawnOnBusThread(
+ dbus::MessageWriter argv_writer(nullptr);
+ writer.OpenArray("ay", &argv_writer);
+
+- for (const std::string& arg : cmdline.argv()) {
++ for (const std::string& arg : cmdline->argv()) {
+ WriteStringAsByteArray(&argv_writer, arg);
+ }
+
+@@ -439,7 +455,7 @@ void FlatpakSandbox::SpawnOnBusThread(
+ WriteFdPairMap(&fds_writer, STDOUT_FILENO, STDOUT_FILENO);
+ WriteFdPairMap(&fds_writer, STDERR_FILENO, STDERR_FILENO);
+
+- for (const auto& pair : launch_options.fds_to_remap) {
++ for (const auto& pair : launch_options->fds_to_remap) {
+ WriteFdPairMap(&fds_writer, pair.first, pair.second);
+ }
+
+@@ -448,7 +464,7 @@ void FlatpakSandbox::SpawnOnBusThread(
+ dbus::MessageWriter env_writer(nullptr);
+ writer.OpenArray("{ss}", &env_writer);
+
+- for (const auto& pair : launch_options.environment) {
++ for (const auto& pair : launch_options->environment) {
+ dbus::MessageWriter entry_writer(nullptr);
+ env_writer.OpenDictEntry(&entry_writer);
+
+@@ -472,11 +488,11 @@ void FlatpakSandbox::SpawnOnBusThread(
+ #else
+ #endif
+
+- if (launch_options.clear_environment) {
++ if (launch_options->clear_environment) {
+ spawn_flags |= kFlatpakSpawn_ClearEnvironment;
+ }
+
+- if (launch_options.kill_on_parent_death) {
++ if (launch_options->kill_on_parent_death) {
+ spawn_flags |= kFlatpakSpawn_WatchBus;
+ }
+
+@@ -485,6 +501,28 @@ void FlatpakSandbox::SpawnOnBusThread(
+ dbus::MessageWriter options_writer(nullptr);
+ writer.OpenArray("{sv}", &options_writer);
+
++ if (!spawn_options->sandbox_expose_ro.empty()) {
++ dbus::MessageWriter entry_writer(nullptr);
++ options_writer.OpenDictEntry(&entry_writer);
++
++ entry_writer.AppendString("sandbox-expose-fd-ro");
++
++ dbus::MessageWriter variant_writer(nullptr);
++ entry_writer.OpenVariant("ah", &variant_writer);
++
++ dbus::MessageWriter fds_writer(nullptr);
++ variant_writer.OpenArray("h", &fds_writer);
++
++ for (const base::ScopedFD& fd : spawn_options->sandbox_expose_ro) {
++ CHECK(fd.is_valid()) << "Invalid spawn expose fd";
++ fds_writer.AppendFileDescriptor(fd.get());
++ }
++
++ variant_writer.CloseContainer(&fds_writer);
++ entry_writer.CloseContainer(&variant_writer);
++ options_writer.CloseContainer(&entry_writer);
++ }
++
+ if (sandbox_flags != 0) {
+ dbus::MessageWriter entry_writer(nullptr);
+ options_writer.OpenDictEntry(&entry_writer);
+diff --git a/sandbox/linux/services/flatpak_sandbox.h b/sandbox/linux/services/flatpak_sandbox.h
+index 167bbc85945ad..de8e7165b4573 100644
+--- a/sandbox/linux/services/flatpak_sandbox.h
++++ b/sandbox/linux/services/flatpak_sandbox.h
+@@ -9,6 +9,8 @@
+ #include "base/compiler_specific.h"
+ #include "base/containers/flat_map.h"
+ #include "base/containers/flat_set.h"
++#include "base/files/file_path.h"
++#include "base/files/scoped_file.h"
+ #include "base/no_destructor.h"
+ #include "base/process/kill.h"
+ #include "base/process/launch.h"
+@@ -34,6 +36,20 @@ namespace sandbox {
+ // it is known inside the sandbox's PID namespace.
+ class SANDBOX_EXPORT FlatpakSandbox {
+ public:
++ class SpawnOptions {
++ public:
++ SpawnOptions() = default;
++ SpawnOptions(const SpawnOptions& other) = delete;
++ SpawnOptions(SpawnOptions&& other) = delete;
++
++ bool ExposePathRo(base::FilePath path);
++
++ private:
++ friend class FlatpakSandbox;
++
++ std::vector<base::ScopedFD> sandbox_expose_ro;
++ };
++
+ static FlatpakSandbox* GetInstance();
+
+ // Represents the level of sandboxing inside a Flatpak. kNone means this is
+@@ -55,7 +71,8 @@ class SANDBOX_EXPORT FlatpakSandbox {
+ // GetRelativePid. This is the reason why a vanilla ProcessId is returned
+ // rather than a base::Process instance.
+ base::Process LaunchProcess(const base::CommandLine& cmdline,
+- const base::LaunchOptions& launch_options);
++ const base::LaunchOptions& launch_options,
++ const SpawnOptions& spawn_options = {});
+
+ // Indefinitely waits for the given process and fills the exit code pointer
+ // if given and non-null. Returns false on wait failure.
+@@ -84,11 +101,13 @@ class SANDBOX_EXPORT FlatpakSandbox {
+ void OnSpawnExitedSignal(dbus::Signal* signal);
+
+ base::ProcessId Spawn(const base::CommandLine& cmdline,
+- const base::LaunchOptions& launch_options);
++ const base::LaunchOptions& launch_options,
++ const SpawnOptions& spawn_options);
+ void SpawnOnBusThread(base::ProcessId* out_external_pid,
+ base::WaitableEvent* event,
+- const base::CommandLine& cmdline,
+- const base::LaunchOptions& launch_options);
++ const base::CommandLine* cmdline,
++ const base::LaunchOptions* launch_options,
++ const SpawnOptions* spawn_options);
+ void OnSpawnResponse(base::ProcessId* out_external_pid,
+ base::WaitableEvent* event,
+ dbus::Response* response,
+--
+2.46.1
+
diff --git a/chromium-132-el8-ffmpeg.patch b/chromium-132-el8-ffmpeg.patch
deleted file mode 100644
index d824d69..0000000
--- a/chromium-132-el8-ffmpeg.patch
+++ /dev/null
@@ -1,52 +0,0 @@
---- /dev/null 2025-01-15 17:59:31.105999986 +0100
-+++ chromium-132.0.6834.83/third_party/ffmpeg/libavcodec/aarch64/autorename_libavcodec_aarch64_vorbisdsp_init.c 2025-01-07 20:49:01.000000000 +0100
-@@ -0,0 +1,2 @@
-+// Automatically generated on Tue Oct 22 17:56:01 2024. See crbug.com/495833.
-+#include "vorbisdsp_init.c"
---- /dev/null 2025-01-15 23:08:30.985344485 +0100
-+++ chromium-132.0.6834.83/third_party/ffmpeg/libavutil/aarch64/autorename_libavutil_aarch64_cpu.c 2025-01-07 20:49:01.000000000 +0100
-@@ -0,0 +1,2 @@
-+// Automatically generated on Tue Oct 22 17:56:01 2024. See crbug.com/495833.
-+#include "cpu.c"
---- /dev/null 2025-01-16 08:50:44.906000351 +0100
-+++ chromium-132.0.6834.83/third_party/ffmpeg/libavutil/aarch64/autorename_libavutil_aarch64_float_dsp_init.c 2025-01-07 20:49:01.000000000 +0100
-@@ -0,0 +1,2 @@
-+// Automatically generated on Tue Oct 22 17:56:01 2024. See crbug.com/495833.
-+#include "float_dsp_init.c"
---- /dev/null 2025-01-16 08:50:44.906000351 +0100
-+++ chromium-132.0.6834.83/third_party/ffmpeg/libavcodec/aarch64/autorename_libavcodec_aarch64_videodsp_init.c 2025-01-07 20:49:01.000000000 +0100
-@@ -0,0 +1,2 @@
-+// Automatically generated on Tue Oct 22 17:56:01 2024. See crbug.com/495833.
-+#include "videodsp_init.c"
---- /dev/null 2025-01-16 10:42:07.086999986 +0100
-+++ chromium-132.0.6834.83/third_party/ffmpeg/libavutil/aarch64/cpu_sve.S 2025-01-07 20:49:01.000000000 +0100
-@@ -0,0 +1,29 @@
-+/*
-+ * Copyright (c) 2023 Martin Storsjo
-+ *
-+ * This file is part of FFmpeg.
-+ *
-+ * FFmpeg is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU Lesser General Public
-+ * License as published by the Free Software Foundation; either
-+ * version 2.1 of the License, or (at your option) any later version.
-+ *
-+ * FFmpeg is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * Lesser General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU Lesser General Public
-+ * License along with FFmpeg; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-+ */
-+
-+#include "config.h"
-+#include "asm.S"
-+
-+ENABLE_SVE
-+
-+function ff_aarch64_sve_length, export=1
-+ cntb x0
-+ ret
-+endfunc
diff --git a/chromium.spec b/chromium.spec
index b03f786..0359a29 100644
--- a/chromium.spec
+++ b/chromium.spec
@@ -282,8 +282,8 @@
%endif
Name: chromium%{chromium_channel}
-Version: 132.0.6834.83
-Release: 2%{?dist}
+Version: 132.0.6834.110
+Release: 1%{?dist}
Summary: A WebKit (Blink) powered web browser that Google doesn't want you to use
Url: http://www.chromium.org/Home
License: BSD-3-Clause AND LGPL-2.1-or-later AND Apache-2.0 AND IJG AND MIT AND GPL-2.0-or-later AND ISC AND OpenSSL AND (MPL-1.1 OR GPL-2.0-only OR LGPL-2.0-only)
@@ -337,9 +337,6 @@ Patch151: chromium-131-qt-ui.patch
# revert, it causes ramdom crash on aarch64
Patch300: chromium-131-revert-decommit-pooled-pages-by-default.patch
-# Workaround for build error on el8 aarch64
-Patch304: chromium-132-el8-ffmpeg.patch
-
# disable memory tagging (epel8 on aarch64) due to new feature IFUNC-Resolver
# it is not supported in old glibc < 2.30, error: fatal error: 'sys/ifunc.h' file not found
Patch305: chromium-124-el8-arm64-memory_tagging.patch
@@ -1060,7 +1057,6 @@ Qt6 UI for chromium.
%if 0%{?rhel} == 8
%ifarch aarch64
-%patch -P304 -p1 -b .el8-ffmpeg
%patch -P305 -p1 -b .el8-memory_tagging
%patch -P306 -p1 -b .el8-ifunc-header
%endif
@@ -1946,6 +1942,11 @@ getent group chrome-remote-desktop >/dev/null || groupadd -r chrome-remote-deskt
%endif
%changelog
+* Thu Jan 23 2025 Than Ngo <than@redhat.com> - 132.0.6834.110-1
+- Update to 132.0.6834.110
+ * High CVE-2025-0611: Object corruption in V8
+ * High CVE-2025-0612: Out of bounds memory access in V8
+
* Thu Jan 16 2025 Fedora Release Engineering <releng@fedoraproject.org> - 132.0.6834.83-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild
diff --git a/clean_ffmpeg.sh b/clean_ffmpeg.sh
index 4b3de8a..f26b2fe 100755
--- a/clean_ffmpeg.sh
+++ b/clean_ffmpeg.sh
@@ -236,6 +236,8 @@ manual_files=" libavcodec/aarch64/h264pred_neon.S \
libavcodec/aarch64/neon.S \
libavcodec/aarch64/vorbisdsp_neon.S \
libavcodec/aarch64/autorename_libavcodec_aarch64_vorbisdsp_neon.S \
+ libavcodec/aarch64/autorename_libavcodec_aarch64_vorbisdsp_init.c \
+ libavcodec/aarch64/autorename_libavcodec_aarch64_videodsp_init.c \
libavcodec/aarch64/vorbisdsp_init.c \
libavcodec/aarch64/vp8dsp_neon.S \
libavcodec/x86/hpeldsp.asm \
@@ -271,8 +273,11 @@ manual_files=" libavcodec/aarch64/h264pred_neon.S \
libavformat/version.c \
libavutil/aarch64/asm.S \
libavutil/aarch64/cpu.c \
+ libavutil/aarch64/cpu_sve.S \
libavutil/aarch64/float_dsp_init.c \
libavutil/aarch64/float_dsp_neon.S \
+ libavutil/aarch64/autorename_libavutil_aarch64_cpu.c \
+ libavutil/aarch64/autorename_libavutil_aarch64_float_dsp_init.c \
libavutil/aarch64/autorename_libavutil_aarch64_float_dsp_neon.S \
libavutil/aarch64/tx_float_neon.S \
libavutil/aarch64/timer.h \
diff --git a/sources b/sources
index 689207a..032d275 100644
--- a/sources
+++ b/sources
@@ -2,4 +2,4 @@ SHA512 (node-v20.6.1-linux-arm64.tar.xz) = adfcaf2c22614797fd69fb46d94c1cbf64dea
SHA512 (node-v20.6.1-linux-x64.tar.xz) = 7e15c05041a9a50f0046266aadb2e092a5aefbec19be1c7c809471add520cb57c7df3c47d88b1888b29bf2979dca3c92adddfd965370fa2a9da4ea02186464fd
SHA512 (linux-arm64-0.19.2.tgz) = 8a0d8fec6786fffcd6954d00820037a55d61e60762c74300df0801f8db27057562c221a063bedfb8df56af9ba80abb366336987e881782c5996e6f871abd3dc6
SHA512 (linux-x64-0.19.2.tgz) = a31cc74c4bfa54f9b75d735a1cfc944d3b5efb7c06bfba9542da9a642ae0b2d235ea00ae84d3ad0572c406405110fe7b61377af0fd15803806ef78d20fc6f05d
-SHA512 (chromium-132.0.6834.83-clean.tar.xz) = af32ca08dcf9e4a9d2c0553079bd3dfe9d27ecb2fc7572843192f519f37364d7d4ccaad987250b45c8ff0c19b9c1bb9c83930cbb1792e3a3ef001cff8c9765a7
+SHA512 (chromium-132.0.6834.110-clean.tar.xz) = 070ebff19ac4c7d3f00f1493d65546e09e49a4ea1df675e58af045a079a024ecabf2fa5aafe2945ec0487da23704516c7a3b155ebc497275c321eeca95664a08
reply other threads:[~2026-08-07 16:07 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=178611883888.1.6420532743217227663.rpms-chromium-0c209b92ae81@fedoraproject.org \
--to=than@fedoraproject.org \
--cc=git-commits@fedoraproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox