You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1326 lines
49 KiB
1326 lines
49 KiB
4 weeks ago
|
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
|
||
|
|