mirror of https://github.com/electron/electron
728 lines
29 KiB
Diff
728 lines
29 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: deepak1556 <hop2deep@gmail.com>
|
|
Date: Wed, 17 Aug 2022 22:04:47 +0900
|
|
Subject: feat: configure launch options for service process
|
|
|
|
- POSIX:
|
|
Allows configuring base::LaunchOptions::fds_to_remap when launching the child process.
|
|
- Win:
|
|
Allows configuring base::LaunchOptions::handles_to_inherit, base::LaunchOptions::stdout_handle
|
|
and base::LaunchOptions::stderr_handle when launching the child process.
|
|
- All:
|
|
Allows configuring base::LauncOptions::current_directory, base::LaunchOptions::enviroment
|
|
and base::LaunchOptions::clear_environment.
|
|
|
|
An example use of this option, UtilityProcess API allows reading the output From
|
|
stdout and stderr of child process by creating a pipe, whose write end is remapped
|
|
to STDOUT_FILENO/STD_OUTPUT_HANDLE and STDERR_FILENO/STD_ERROR_HANDLE allowing the
|
|
parent process to read from the pipe.
|
|
|
|
diff --git a/content/browser/child_process_launcher.h b/content/browser/child_process_launcher.h
|
|
index 613feee88115d32905a3f8889cdf51d71cd5b4ec..da2fefd7b6e93a6f8b6eb008ebaac976f4ce64ea 100644
|
|
--- a/content/browser/child_process_launcher.h
|
|
+++ b/content/browser/child_process_launcher.h
|
|
@@ -32,6 +32,7 @@
|
|
|
|
#if BUILDFLAG(IS_WIN)
|
|
#include "base/win/windows_types.h"
|
|
+#include "base/win/scoped_handle.h"
|
|
#endif
|
|
|
|
#if BUILDFLAG(IS_POSIX)
|
|
@@ -165,7 +166,10 @@ struct ChildProcessLauncherFileData {
|
|
delete;
|
|
~ChildProcessLauncherFileData();
|
|
|
|
-#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
|
|
+#if BUILDFLAG(IS_WIN)
|
|
+ base::win::ScopedHandle stdout_handle;
|
|
+ base::win::ScopedHandle stderr_handle;
|
|
+#elif BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
|
|
// Files opened by the browser and passed as corresponding file descriptors
|
|
// in the child process. If a FilePath is provided, the file will be opened
|
|
// and the descriptor cached for future process launches. If a ScopedFD is
|
|
@@ -180,6 +184,15 @@ struct ChildProcessLauncherFileData {
|
|
std::map<std::string, absl::variant<base::FilePath, base::ScopedFD>>
|
|
files_to_preload;
|
|
#endif
|
|
+
|
|
+#if BUILDFLAG(IS_POSIX)
|
|
+ // Map of file descriptors to pass. This is used instead of
|
|
+ // `files_to_preload` when the data needs to be installed at an exact FD
|
|
+ // number in the new process.
|
|
+ //
|
|
+ // Currently only supported on POSIX platforms.
|
|
+ std::map<int, base::ScopedFD> additional_remapped_fds;
|
|
+#endif
|
|
};
|
|
|
|
// Launches a process asynchronously and notifies the client of the process
|
|
diff --git a/content/browser/child_process_launcher_helper_linux.cc b/content/browser/child_process_launcher_helper_linux.cc
|
|
index 31a2a14a95540477297943df9b09b1e4659a884d..c02a81b1bd14a300dbbb47ad7aac2d2d7f3bb10f 100644
|
|
--- a/content/browser/child_process_launcher_helper_linux.cc
|
|
+++ b/content/browser/child_process_launcher_helper_linux.cc
|
|
@@ -64,6 +64,11 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
|
|
options->fds_to_remap.emplace_back(sandbox_fd, GetSandboxFD());
|
|
}
|
|
|
|
+ for (const auto& remapped_fd : file_data_->additional_remapped_fds) {
|
|
+ options->fds_to_remap.emplace_back(remapped_fd.second.get(),
|
|
+ remapped_fd.first);
|
|
+ }
|
|
+
|
|
// (For Electron), if we're launching without zygote, that means we're
|
|
// launching an unsandboxed process (since all sandboxed processes are
|
|
// forked from the zygote). Relax the allow_new_privs option to permit
|
|
@@ -73,7 +78,9 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
|
|
options->allow_new_privs = true;
|
|
}
|
|
|
|
+ options->current_directory = delegate_->GetCurrentDirectory();
|
|
options->environment = delegate_->GetEnvironment();
|
|
+ options->clear_environment = !delegate_->ShouldInheritEnvironment();
|
|
} else {
|
|
DCHECK(GetZygoteForLaunch());
|
|
// Environment variables could be supported in the future, but are not
|
|
diff --git a/content/browser/child_process_launcher_helper_mac.cc b/content/browser/child_process_launcher_helper_mac.cc
|
|
index e1c5d814236d306e427dc5f1bab3405c0fb4dd7e..bc991a819e20d586431115e530c44a83b231eb45 100644
|
|
--- a/content/browser/child_process_launcher_helper_mac.cc
|
|
+++ b/content/browser/child_process_launcher_helper_mac.cc
|
|
@@ -123,7 +123,8 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
|
|
'mojo', base::MachRendezvousPort(endpoint.TakeMachReceiveRight())));
|
|
|
|
options->environment = delegate_->GetEnvironment();
|
|
-
|
|
+ options->clear_environment = !delegate_->ShouldInheritEnvironment();
|
|
+ options->current_directory = delegate_->GetCurrentDirectory();
|
|
options->disclaim_responsibility = delegate_->DisclaimResponsibility();
|
|
options->enable_cpu_security_mitigations =
|
|
delegate_->EnableCpuSecurityMitigations();
|
|
@@ -187,6 +188,11 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
|
|
base::StringPrintf("%s%d", sandbox::switches::kSeatbeltClient, pipe));
|
|
}
|
|
|
|
+ for (const auto& remapped_fd : file_data_->additional_remapped_fds) {
|
|
+ options->fds_to_remap.emplace_back(remapped_fd.second.get(),
|
|
+ remapped_fd.first);
|
|
+ }
|
|
+
|
|
return true;
|
|
}
|
|
|
|
diff --git a/content/browser/child_process_launcher_helper_win.cc b/content/browser/child_process_launcher_helper_win.cc
|
|
index 2a01487c8ff837357f6d62dba80115b0ec64c343..8b1ed51630dc4fe77bd0edadb85f04fb8962cdd8 100644
|
|
--- a/content/browser/child_process_launcher_helper_win.cc
|
|
+++ b/content/browser/child_process_launcher_helper_win.cc
|
|
@@ -24,6 +24,8 @@
|
|
#include "mojo/public/cpp/platform/named_platform_channel.h"
|
|
#include "mojo/public/cpp/platform/platform_channel.h"
|
|
|
|
+#include <windows.h>
|
|
+
|
|
namespace {
|
|
|
|
// Helper to avoid marking the log file as non-executable every time we launch a
|
|
@@ -132,6 +134,30 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
|
|
mojo_channel_->PrepareToPassRemoteEndpoint(&options->handles_to_inherit,
|
|
command_line());
|
|
}
|
|
+
|
|
+ if (file_data_->stdout_handle.IsValid() || file_data_->stderr_handle.IsValid()) {
|
|
+ // base::LaunchProcess requires that if any of the stdio handle is customized then
|
|
+ // the other two handles should also be set.
|
|
+ // https://source.chromium.org/chromium/chromium/src/+/main:base/process/launch_win.cc;l=341-350
|
|
+ options->stdin_handle = INVALID_HANDLE_VALUE;
|
|
+ if (file_data_->stdout_handle.IsValid()) {
|
|
+ options->stdout_handle = file_data_->stdout_handle.get();
|
|
+ } else {
|
|
+ options->stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
+ }
|
|
+
|
|
+ if (file_data_->stderr_handle.IsValid()) {
|
|
+ options->stderr_handle = file_data_->stderr_handle.get();
|
|
+ } else {
|
|
+ options->stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
|
|
+ }
|
|
+ options->handles_to_inherit.push_back(options->stdout_handle);
|
|
+ options->handles_to_inherit.push_back(options->stderr_handle);
|
|
+ }
|
|
+
|
|
+ options->current_directory = delegate_->GetCurrentDirectory();
|
|
+ options->environment = delegate_->GetEnvironment();
|
|
+ options->clear_environment = !delegate_->ShouldInheritEnvironment();
|
|
return true;
|
|
}
|
|
|
|
@@ -159,7 +185,7 @@ ChildProcessLauncherHelper::LaunchProcessOnLauncherThread(
|
|
ChildProcessLauncherHelper::Process process;
|
|
*launch_result =
|
|
StartSandboxedProcess(delegate_.get(), *command_line(),
|
|
- options->handles_to_inherit, &process.process);
|
|
+ options, &process.process);
|
|
return process;
|
|
}
|
|
|
|
diff --git a/content/browser/service_process_host_impl.cc b/content/browser/service_process_host_impl.cc
|
|
index be6402b33d7e0e2aab7cbb2844ba4600a166e7a9..642f8b6da39615d1c68584ff18fc57ceb95b84b2 100644
|
|
--- a/content/browser/service_process_host_impl.cc
|
|
+++ b/content/browser/service_process_host_impl.cc
|
|
@@ -204,6 +204,16 @@ void LaunchServiceProcess(mojo::GenericPendingReceiver receiver,
|
|
options.allow_gpu_client.value()) {
|
|
host->SetAllowGpuClient();
|
|
}
|
|
+
|
|
+#if BUILDFLAG(IS_WIN)
|
|
+ host->SetStdioHandles(std::move(options.stdout_handle), std::move(options.stderr_handle));
|
|
+#elif BUILDFLAG(IS_POSIX)
|
|
+ host->SetAdditionalFds(std::move(options.fds_to_remap));
|
|
+#endif
|
|
+ host->SetCurrentDirectory(options.current_directory);
|
|
+ host->SetEnv(options.environment);
|
|
+ if (options.clear_environment)
|
|
+ host->ClearEnvironment();
|
|
host->Start();
|
|
host->GetChildProcess()->BindServiceInterface(std::move(receiver));
|
|
}
|
|
diff --git a/content/browser/utility_process_host.cc b/content/browser/utility_process_host.cc
|
|
index 4bb24555db8061318a25e02590618d5557383dd5..c564b64f25c3c2bf87ed5a93b0ce601d73aab177 100644
|
|
--- a/content/browser/utility_process_host.cc
|
|
+++ b/content/browser/utility_process_host.cc
|
|
@@ -178,11 +178,13 @@ const ChildProcessData& UtilityProcessHost::GetData() {
|
|
return process_->GetData();
|
|
}
|
|
|
|
-#if BUILDFLAG(IS_POSIX)
|
|
void UtilityProcessHost::SetEnv(const base::EnvironmentMap& env) {
|
|
env_ = env;
|
|
}
|
|
-#endif
|
|
+
|
|
+void UtilityProcessHost::ClearEnvironment() {
|
|
+ inherit_environment_ = false;
|
|
+}
|
|
|
|
bool UtilityProcessHost::Start() {
|
|
return StartProcess();
|
|
@@ -229,6 +231,24 @@ void UtilityProcessHost::SetZygoteForTesting(ZygoteCommunication* handle) {
|
|
}
|
|
#endif // BUILDFLAG(USE_ZYGOTE)
|
|
|
|
+#if BUILDFLAG(IS_WIN)
|
|
+void UtilityProcessHost::SetStdioHandles(
|
|
+ base::win::ScopedHandle stdout_handle,
|
|
+ base::win::ScopedHandle stderr_handle) {
|
|
+ stdout_handle_ = std::move(stdout_handle);
|
|
+ stderr_handle_ = std::move(stderr_handle);
|
|
+}
|
|
+#elif BUILDFLAG(IS_POSIX)
|
|
+void UtilityProcessHost::SetAdditionalFds(base::FileHandleMappingVector mapping) {
|
|
+ fds_to_remap_ = std::move(mapping);
|
|
+}
|
|
+#endif
|
|
+
|
|
+void UtilityProcessHost::SetCurrentDirectory(
|
|
+ const base::FilePath& cwd) {
|
|
+ current_directory_ = cwd;
|
|
+}
|
|
+
|
|
mojom::ChildProcess* UtilityProcessHost::GetChildProcess() {
|
|
return static_cast<ChildProcessHostImpl*>(process_->GetHost())
|
|
->child_process();
|
|
@@ -438,9 +458,22 @@ bool UtilityProcessHost::StartProcess() {
|
|
}
|
|
#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH)
|
|
|
|
+#if BUILDFLAG(IS_WIN)
|
|
+ file_data_->stdout_handle = std::move(stdout_handle_);
|
|
+ file_data_->stderr_handle = std::move(stderr_handle_);
|
|
+#elif BUILDFLAG(IS_POSIX)
|
|
+ if (!fds_to_remap_.empty()) {
|
|
+ for (const auto& remapped_fd : fds_to_remap_) {
|
|
+ file_data_->additional_remapped_fds.emplace(
|
|
+ remapped_fd.second, remapped_fd.first);
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
+
|
|
std::unique_ptr<UtilitySandboxedProcessLauncherDelegate> delegate =
|
|
std::make_unique<UtilitySandboxedProcessLauncherDelegate>(
|
|
- sandbox_type_, env_, *cmd_line);
|
|
+ sandbox_type_, env_, current_directory_, *cmd_line,
|
|
+ inherit_environment_);
|
|
|
|
#if BUILDFLAG(IS_WIN)
|
|
if (!preload_libraries_.empty()) {
|
|
diff --git a/content/browser/utility_process_host.h b/content/browser/utility_process_host.h
|
|
index 9791ae2f761043b9eecd9064a6fd39a6e2339af4..1083f1683a05825f51f5b2d71f8107d910fa2474 100644
|
|
--- a/content/browser/utility_process_host.h
|
|
+++ b/content/browser/utility_process_host.h
|
|
@@ -29,6 +29,10 @@
|
|
#include "content/public/common/zygote/zygote_handle.h"
|
|
#endif // BUILDFLAG(USE_ZYGOTE)
|
|
|
|
+#if BUILDFLAG(IS_WIN)
|
|
+#include "base/win/scoped_handle.h"
|
|
+#endif
|
|
+
|
|
namespace base {
|
|
class Thread;
|
|
} // namespace base
|
|
@@ -98,9 +102,13 @@ class CONTENT_EXPORT UtilityProcessHost
|
|
|
|
// Returns information about the utility child process.
|
|
const ChildProcessData& GetData();
|
|
-#if BUILDFLAG(IS_POSIX)
|
|
+
|
|
+ // Set/Unset environment variables.
|
|
void SetEnv(const base::EnvironmentMap& env);
|
|
-#endif
|
|
+
|
|
+ // Clear the environment for the new process before processing
|
|
+ // changes from SetEnv.
|
|
+ void ClearEnvironment();
|
|
|
|
// Starts the utility process.
|
|
bool Start();
|
|
@@ -138,6 +146,16 @@ class CONTENT_EXPORT UtilityProcessHost
|
|
void SetZygoteForTesting(ZygoteCommunication* handle);
|
|
#endif // BUILDFLAG(USE_ZYGOTE)
|
|
|
|
+#if BUILDFLAG(IS_WIN)
|
|
+ void SetStdioHandles(base::win::ScopedHandle stdout_handle,
|
|
+ base::win::ScopedHandle stderr_handle);
|
|
+#elif BUILDFLAG(IS_POSIX)
|
|
+ void SetAdditionalFds(base::FileHandleMappingVector mapping);
|
|
+#endif
|
|
+
|
|
+ // Sets the working directory of the process.
|
|
+ void SetCurrentDirectory(const base::FilePath& cwd);
|
|
+
|
|
// Returns a control interface for the running child process.
|
|
mojom::ChildProcess* GetChildProcess();
|
|
|
|
@@ -191,6 +209,22 @@ class CONTENT_EXPORT UtilityProcessHost
|
|
std::optional<raw_ptr<ZygoteCommunication>> zygote_for_testing_;
|
|
#endif // BUILDFLAG(USE_ZYGOTE)
|
|
|
|
+#if BUILDFLAG(IS_WIN)
|
|
+ // Specifies the handles for redirection of stdout and stderr.
|
|
+ base::win::ScopedHandle stdout_handle_;
|
|
+ base::win::ScopedHandle stderr_handle_;
|
|
+#elif BUILDFLAG(IS_POSIX)
|
|
+ // Specifies file descriptors to propagate into the child process
|
|
+ // based on the mapping.
|
|
+ base::FileHandleMappingVector fds_to_remap_;
|
|
+#endif
|
|
+
|
|
+ // If not empty, change to this directory before executing the new process.
|
|
+ base::FilePath current_directory_;
|
|
+
|
|
+ // Inherit enviroment from parent process.
|
|
+ bool inherit_environment_ = true;
|
|
+
|
|
// Indicates whether the process has been successfully launched yet, or if
|
|
// launch failed.
|
|
enum class LaunchState {
|
|
diff --git a/content/browser/utility_sandbox_delegate.cc b/content/browser/utility_sandbox_delegate.cc
|
|
index bb7667de8bb189d5daccf0ae824bffbb092f1c22..2e5beb5ac9dac293ca3d2824972d26d8fcd9fe06 100644
|
|
--- a/content/browser/utility_sandbox_delegate.cc
|
|
+++ b/content/browser/utility_sandbox_delegate.cc
|
|
@@ -29,13 +29,15 @@ UtilitySandboxedProcessLauncherDelegate::
|
|
UtilitySandboxedProcessLauncherDelegate(
|
|
sandbox::mojom::Sandbox sandbox_type,
|
|
const base::EnvironmentMap& env,
|
|
- const base::CommandLine& cmd_line)
|
|
+ const base::FilePath& cwd,
|
|
+ const base::CommandLine& cmd_line,
|
|
+ bool inherit_environment)
|
|
:
|
|
-#if BUILDFLAG(IS_POSIX)
|
|
env_(env),
|
|
-#endif
|
|
+ current_directory_(cwd),
|
|
sandbox_type_(sandbox_type),
|
|
- cmd_line_(cmd_line) {
|
|
+ cmd_line_(cmd_line),
|
|
+ inherit_environment_(inherit_environment) {
|
|
#if DCHECK_IS_ON()
|
|
bool supported_sandbox_type =
|
|
sandbox_type_ == sandbox::mojom::Sandbox::kNoSandbox ||
|
|
@@ -97,11 +99,17 @@ UtilitySandboxedProcessLauncherDelegate::GetSandboxType() {
|
|
return sandbox_type_;
|
|
}
|
|
|
|
-#if BUILDFLAG(IS_POSIX)
|
|
base::EnvironmentMap UtilitySandboxedProcessLauncherDelegate::GetEnvironment() {
|
|
return env_;
|
|
}
|
|
-#endif // BUILDFLAG(IS_POSIX)
|
|
+
|
|
+bool UtilitySandboxedProcessLauncherDelegate::ShouldInheritEnvironment() {
|
|
+ return inherit_environment_;
|
|
+}
|
|
+
|
|
+base::FilePath UtilitySandboxedProcessLauncherDelegate::GetCurrentDirectory() {
|
|
+ return current_directory_;
|
|
+}
|
|
|
|
#if BUILDFLAG(USE_ZYGOTE)
|
|
ZygoteCommunication* UtilitySandboxedProcessLauncherDelegate::GetZygote() {
|
|
diff --git a/content/browser/utility_sandbox_delegate.h b/content/browser/utility_sandbox_delegate.h
|
|
index c1e56dc93b80594ffb55e11291e7bd152f029d61..928f3f693eed4252d9d34a64dd392af7e48e4190 100644
|
|
--- a/content/browser/utility_sandbox_delegate.h
|
|
+++ b/content/browser/utility_sandbox_delegate.h
|
|
@@ -29,7 +29,9 @@ class UtilitySandboxedProcessLauncherDelegate
|
|
public:
|
|
UtilitySandboxedProcessLauncherDelegate(sandbox::mojom::Sandbox sandbox_type,
|
|
const base::EnvironmentMap& env,
|
|
- const base::CommandLine& cmd_line);
|
|
+ const base::FilePath& cwd,
|
|
+ const base::CommandLine& cmd_line,
|
|
+ bool inherit_environment);
|
|
~UtilitySandboxedProcessLauncherDelegate() override;
|
|
|
|
sandbox::mojom::Sandbox GetSandboxType() override;
|
|
@@ -55,18 +57,16 @@ class UtilitySandboxedProcessLauncherDelegate
|
|
ZygoteCommunication* GetZygote() override;
|
|
#endif // BUILDFLAG(USE_ZYGOTE)
|
|
|
|
-#if BUILDFLAG(IS_POSIX)
|
|
base::EnvironmentMap GetEnvironment() override;
|
|
-#endif // BUILDFLAG(IS_POSIX)
|
|
+ bool ShouldInheritEnvironment() override;
|
|
+ base::FilePath GetCurrentDirectory() override;
|
|
|
|
#if BUILDFLAG(USE_ZYGOTE)
|
|
void SetZygote(ZygoteCommunication* handle);
|
|
#endif // BUILDFLAG(USE_ZYGOTE_HANDLE)
|
|
|
|
private:
|
|
-#if BUILDFLAG(IS_POSIX)
|
|
base::EnvironmentMap env_;
|
|
-#endif // BUILDFLAG(IS_POSIX)
|
|
|
|
#if BUILDFLAG(IS_WIN)
|
|
std::vector<base::FilePath> preload_libraries_;
|
|
@@ -76,8 +76,10 @@ class UtilitySandboxedProcessLauncherDelegate
|
|
std::optional<raw_ptr<ZygoteCommunication>> zygote_;
|
|
#endif // BUILDFLAG(USE_ZYGOTE)
|
|
|
|
+ base::FilePath current_directory_;
|
|
sandbox::mojom::Sandbox sandbox_type_;
|
|
base::CommandLine cmd_line_;
|
|
+ bool inherit_environment_;
|
|
};
|
|
} // namespace content
|
|
|
|
diff --git a/content/common/sandbox_init_win.cc b/content/common/sandbox_init_win.cc
|
|
index 498f60227d13eb2e476413f88eaa58cc0babf461..619639ad5d22a1121b0e0d5f2c9e3c10394cdbd7 100644
|
|
--- a/content/common/sandbox_init_win.cc
|
|
+++ b/content/common/sandbox_init_win.cc
|
|
@@ -23,7 +23,7 @@ namespace content {
|
|
sandbox::ResultCode StartSandboxedProcess(
|
|
SandboxedProcessLauncherDelegate* delegate,
|
|
const base::CommandLine& target_command_line,
|
|
- const base::HandlesToInheritVector& handles_to_inherit,
|
|
+ const base::LaunchOptions* options,
|
|
base::Process* process) {
|
|
std::string type_str =
|
|
target_command_line.GetSwitchValueASCII(switches::kProcessType);
|
|
@@ -45,7 +45,7 @@ sandbox::ResultCode StartSandboxedProcess(
|
|
}
|
|
|
|
return sandbox::policy::SandboxWin::StartSandboxedProcess(
|
|
- full_command_line, type_str, handles_to_inherit, delegate, process);
|
|
+ full_command_line, type_str, options, delegate, process);
|
|
}
|
|
|
|
} // namespace content
|
|
diff --git a/content/public/browser/service_process_host.cc b/content/public/browser/service_process_host.cc
|
|
index 8defae52a201a97c402e304216ce772a717a9f7e..a3cdeab1c22cf9f1b5ea0c25d2d7cbff9b68b683 100644
|
|
--- a/content/public/browser/service_process_host.cc
|
|
+++ b/content/public/browser/service_process_host.cc
|
|
@@ -52,12 +52,45 @@ ServiceProcessHost::Options::WithExtraCommandLineSwitches(
|
|
return *this;
|
|
}
|
|
|
|
+#if BUILDFLAG(IS_WIN)
|
|
+ServiceProcessHost::Options& ServiceProcessHost::Options::WithStdoutHandle(
|
|
+ base::win::ScopedHandle handle) {
|
|
+ stdout_handle = std::move(handle);
|
|
+ return *this;
|
|
+}
|
|
+
|
|
+ServiceProcessHost::Options& ServiceProcessHost::Options::WithStderrHandle(
|
|
+ base::win::ScopedHandle handle) {
|
|
+ stderr_handle = std::move(handle);
|
|
+ return *this;
|
|
+}
|
|
+#elif BUILDFLAG(IS_POSIX)
|
|
+ServiceProcessHost::Options& ServiceProcessHost::Options::WithAdditionalFds(
|
|
+ base::FileHandleMappingVector mapping) {
|
|
+ fds_to_remap = std::move(mapping);
|
|
+ return *this;
|
|
+}
|
|
+#endif
|
|
+
|
|
ServiceProcessHost::Options& ServiceProcessHost::Options::WithProcessCallback(
|
|
base::OnceCallback<void(const base::Process&)> callback) {
|
|
process_callback = std::move(callback);
|
|
return *this;
|
|
}
|
|
|
|
+ServiceProcessHost::Options& ServiceProcessHost::Options::WithCurrentDirectory(
|
|
+ const base::FilePath& cwd) {
|
|
+ current_directory = cwd;
|
|
+ return *this;
|
|
+}
|
|
+
|
|
+ServiceProcessHost::Options& ServiceProcessHost::Options::WithEnvironment(
|
|
+ const base::EnvironmentMap& env, bool new_environment) {
|
|
+ environment = env;
|
|
+ clear_environment = new_environment;
|
|
+ return *this;
|
|
+}
|
|
+
|
|
#if BUILDFLAG(IS_WIN)
|
|
ServiceProcessHost::Options&
|
|
ServiceProcessHost::Options::WithPreloadedLibraries(
|
|
diff --git a/content/public/browser/service_process_host.h b/content/public/browser/service_process_host.h
|
|
index 0062d2cb6634b8b29977a0312516b1b13936b40a..22e1191b57f56aa31b2c82fcc3ec0972f16752a8 100644
|
|
--- a/content/public/browser/service_process_host.h
|
|
+++ b/content/public/browser/service_process_host.h
|
|
@@ -14,6 +14,7 @@
|
|
#include "base/command_line.h"
|
|
#include "base/functional/callback.h"
|
|
#include "base/observer_list_types.h"
|
|
+#include "base/process/launch.h"
|
|
#include "base/process/process_handle.h"
|
|
#include "content/common/content_export.h"
|
|
#include "content/public/browser/service_process_info.h"
|
|
@@ -28,6 +29,10 @@
|
|
#include "base/types/pass_key.h"
|
|
#endif // BUILDFLAG(IS_WIN)
|
|
|
|
+#if BUILDFLAG(IS_WIN)
|
|
+#include "base/win/scoped_handle.h"
|
|
+#endif
|
|
+
|
|
namespace base {
|
|
class Process;
|
|
} // namespace base
|
|
@@ -94,11 +99,30 @@ class CONTENT_EXPORT ServiceProcessHost {
|
|
// Specifies extra command line switches to append before launch.
|
|
Options& WithExtraCommandLineSwitches(std::vector<std::string> switches);
|
|
|
|
+#if BUILDFLAG(IS_WIN)
|
|
+ // Specifies the handles for redirection of stdout and stderr.
|
|
+ Options& WithStdoutHandle(base::win::ScopedHandle stdout_handle);
|
|
+ Options& WithStderrHandle(base::win::ScopedHandle stderr_handle);
|
|
+#elif BUILDFLAG(IS_POSIX)
|
|
+ // Specifies file descriptors to propagate into the child process
|
|
+ // based on the mapping.
|
|
+ Options& WithAdditionalFds(base::FileHandleMappingVector mapping);
|
|
+#endif
|
|
+
|
|
// Specifies a callback to be invoked with service process once it's
|
|
// launched. Will be on UI thread.
|
|
Options& WithProcessCallback(
|
|
base::OnceCallback<void(const base::Process&)>);
|
|
|
|
+ // Specifies the working directory for the launched process.
|
|
+ Options& WithCurrentDirectory(const base::FilePath& cwd);
|
|
+
|
|
+ // Specifies the environment that should be applied to the process.
|
|
+ // |new_environment| controls whether the process should inherit
|
|
+ // environment from the parent process.
|
|
+ Options& WithEnvironment(const base::EnvironmentMap& environment,
|
|
+ bool new_environment);
|
|
+
|
|
#if BUILDFLAG(IS_WIN)
|
|
// Specifies libraries to preload before the sandbox is locked down. Paths
|
|
// should be absolute paths. Libraries will be preloaded before sandbox
|
|
@@ -127,11 +151,20 @@ class CONTENT_EXPORT ServiceProcessHost {
|
|
std::optional<GURL> site;
|
|
std::optional<int> child_flags;
|
|
std::vector<std::string> extra_switches;
|
|
+#if BUILDFLAG(IS_WIN)
|
|
+ base::win::ScopedHandle stdout_handle;
|
|
+ base::win::ScopedHandle stderr_handle;
|
|
+#elif BUILDFLAG(IS_POSIX)
|
|
+ base::FileHandleMappingVector fds_to_remap;
|
|
+#endif
|
|
base::OnceCallback<void(const base::Process&)> process_callback;
|
|
#if BUILDFLAG(IS_WIN)
|
|
std::vector<base::FilePath> preload_libraries;
|
|
#endif // BUILDFLAG(IS_WIN)
|
|
std::optional<bool> allow_gpu_client;
|
|
+ base::FilePath current_directory;
|
|
+ base::EnvironmentMap environment;
|
|
+ bool clear_environment = false;
|
|
};
|
|
|
|
// An interface which can be implemented and registered/unregistered with
|
|
diff --git a/content/public/common/sandbox_init_win.h b/content/public/common/sandbox_init_win.h
|
|
index 9bb4b30ba0f5d37ec2b28f0848d94f34c24f9423..b614fef01ee5cdf81b7112be721b851c454756a2 100644
|
|
--- a/content/public/common/sandbox_init_win.h
|
|
+++ b/content/public/common/sandbox_init_win.h
|
|
@@ -29,7 +29,7 @@ class SandboxedProcessLauncherDelegate;
|
|
CONTENT_EXPORT sandbox::ResultCode StartSandboxedProcess(
|
|
SandboxedProcessLauncherDelegate* delegate,
|
|
const base::CommandLine& target_command_line,
|
|
- const base::HandlesToInheritVector& handles_to_inherit,
|
|
+ const base::LaunchOptions* options,
|
|
base::Process* process);
|
|
|
|
} // namespace content
|
|
diff --git a/content/public/common/sandboxed_process_launcher_delegate.cc b/content/public/common/sandboxed_process_launcher_delegate.cc
|
|
index 9c1aa450f32b6812d4a87cd0b9ee0dfb1a9557f4..3360302b4511ed914ac2d5756dcc7edf7e675631 100644
|
|
--- a/content/public/common/sandboxed_process_launcher_delegate.cc
|
|
+++ b/content/public/common/sandboxed_process_launcher_delegate.cc
|
|
@@ -68,11 +68,17 @@ ZygoteCommunication* SandboxedProcessLauncherDelegate::GetZygote() {
|
|
}
|
|
#endif // BUILDFLAG(USE_ZYGOTE)
|
|
|
|
-#if BUILDFLAG(IS_POSIX)
|
|
base::EnvironmentMap SandboxedProcessLauncherDelegate::GetEnvironment() {
|
|
return base::EnvironmentMap();
|
|
}
|
|
-#endif // BUILDFLAG(IS_POSIX)
|
|
+
|
|
+bool SandboxedProcessLauncherDelegate::ShouldInheritEnvironment() {
|
|
+ return true;
|
|
+}
|
|
+
|
|
+base::FilePath SandboxedProcessLauncherDelegate::GetCurrentDirectory() {
|
|
+ return base::FilePath();
|
|
+}
|
|
|
|
#if BUILDFLAG(IS_MAC)
|
|
|
|
diff --git a/content/public/common/sandboxed_process_launcher_delegate.h b/content/public/common/sandboxed_process_launcher_delegate.h
|
|
index cb43aa14c9742f3788ae58c3e49b890cd532f327..6a738f7aade504f2ff3bb6647a0da8f8d1933de2 100644
|
|
--- a/content/public/common/sandboxed_process_launcher_delegate.h
|
|
+++ b/content/public/common/sandboxed_process_launcher_delegate.h
|
|
@@ -6,6 +6,7 @@
|
|
#define CONTENT_PUBLIC_COMMON_SANDBOXED_PROCESS_LAUNCHER_DELEGATE_H_
|
|
|
|
#include "base/environment.h"
|
|
+#include "base/files/file_path.h"
|
|
#include "base/files/scoped_file.h"
|
|
#include "base/process/process.h"
|
|
#include "build/build_config.h"
|
|
@@ -57,10 +58,14 @@ class CONTENT_EXPORT SandboxedProcessLauncherDelegate
|
|
virtual ZygoteCommunication* GetZygote();
|
|
#endif // BUILDFLAG(USE_ZYGOTE)
|
|
|
|
-#if BUILDFLAG(IS_POSIX)
|
|
// Override this if the process needs a non-empty environment map.
|
|
virtual base::EnvironmentMap GetEnvironment();
|
|
-#endif // BUILDFLAG(IS_POSIX)
|
|
+
|
|
+ // Override this if the process should not inherit parent environment.
|
|
+ virtual bool ShouldInheritEnvironment();
|
|
+
|
|
+ // Specifies the directory to change to before executing the process.
|
|
+ virtual base::FilePath GetCurrentDirectory();
|
|
|
|
#if BUILDFLAG(IS_MAC)
|
|
// Whether or not to disclaim TCC responsibility for the process, defaults to
|
|
diff --git a/sandbox/policy/win/sandbox_win.cc b/sandbox/policy/win/sandbox_win.cc
|
|
index d8d0cafa87f305fa2fab28ab582e3fa9c360bd71..ede9c798615f4f4c77de56d9d4e20a939bf0665c 100644
|
|
--- a/sandbox/policy/win/sandbox_win.cc
|
|
+++ b/sandbox/policy/win/sandbox_win.cc
|
|
@@ -763,11 +763,9 @@ base::win::ScopedHandle CreateUnsandboxedJob() {
|
|
// command line flag.
|
|
ResultCode LaunchWithoutSandbox(
|
|
const base::CommandLine& cmd_line,
|
|
- const base::HandlesToInheritVector& handles_to_inherit,
|
|
+ base::LaunchOptions options,
|
|
SandboxDelegate* delegate,
|
|
base::Process* process) {
|
|
- base::LaunchOptions options;
|
|
- options.handles_to_inherit = handles_to_inherit;
|
|
// Network process runs in a job even when unsandboxed. This is to ensure it
|
|
// does not outlive the browser, which could happen if there is a lot of I/O
|
|
// on process shutdown, in which case TerminateProcess can fail. See
|
|
@@ -998,7 +996,7 @@ bool SandboxWin::InitTargetServices(TargetServices* target_services) {
|
|
ResultCode SandboxWin::GeneratePolicyForSandboxedProcess(
|
|
const base::CommandLine& cmd_line,
|
|
const std::string& process_type,
|
|
- const base::HandlesToInheritVector& handles_to_inherit,
|
|
+ const base::LaunchOptions* options,
|
|
SandboxDelegate* delegate,
|
|
TargetPolicy* policy) {
|
|
const base::CommandLine& launcher_process_command_line =
|
|
@@ -1012,7 +1010,7 @@ ResultCode SandboxWin::GeneratePolicyForSandboxedProcess(
|
|
}
|
|
|
|
// Add any handles to be inherited to the policy.
|
|
- for (HANDLE handle : handles_to_inherit)
|
|
+ for (HANDLE handle : options->handles_to_inherit)
|
|
policy->AddHandleToShare(handle);
|
|
|
|
if (!policy->GetConfig()->IsConfigured()) {
|
|
@@ -1027,6 +1025,13 @@ ResultCode SandboxWin::GeneratePolicyForSandboxedProcess(
|
|
// have no effect. These calls can fail with SBOX_ERROR_BAD_PARAMS.
|
|
policy->SetStdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE));
|
|
policy->SetStderrHandle(GetStdHandle(STD_ERROR_HANDLE));
|
|
+#else
|
|
+ if (options->stdout_handle != nullptr && options->stdout_handle != INVALID_HANDLE_VALUE) {
|
|
+ policy->SetStdoutHandle(options->stdout_handle);
|
|
+ }
|
|
+ if (options->stderr_handle != nullptr && options->stderr_handle != INVALID_HANDLE_VALUE) {
|
|
+ policy->SetStderrHandle(options->stderr_handle);
|
|
+ }
|
|
#endif
|
|
|
|
if (!delegate->PreSpawnTarget(policy))
|
|
@@ -1039,7 +1044,7 @@ ResultCode SandboxWin::GeneratePolicyForSandboxedProcess(
|
|
ResultCode SandboxWin::StartSandboxedProcess(
|
|
const base::CommandLine& cmd_line,
|
|
const std::string& process_type,
|
|
- const base::HandlesToInheritVector& handles_to_inherit,
|
|
+ const base::LaunchOptions* options,
|
|
SandboxDelegate* delegate,
|
|
base::Process* process) {
|
|
SandboxLaunchTimer timer;
|
|
@@ -1047,7 +1052,7 @@ ResultCode SandboxWin::StartSandboxedProcess(
|
|
// Avoid making a policy if we won't use it.
|
|
if (IsUnsandboxedProcess(delegate->GetSandboxType(), cmd_line,
|
|
*base::CommandLine::ForCurrentProcess())) {
|
|
- return LaunchWithoutSandbox(cmd_line, handles_to_inherit, delegate,
|
|
+ return LaunchWithoutSandbox(cmd_line, *options, delegate,
|
|
process);
|
|
}
|
|
|
|
@@ -1055,7 +1060,7 @@ ResultCode SandboxWin::StartSandboxedProcess(
|
|
timer.OnPolicyCreated();
|
|
|
|
ResultCode result = GeneratePolicyForSandboxedProcess(
|
|
- cmd_line, process_type, handles_to_inherit, delegate, policy.get());
|
|
+ cmd_line, process_type, options, delegate, policy.get());
|
|
if (SBOX_ALL_OK != result)
|
|
return result;
|
|
timer.OnPolicyGenerated();
|
|
diff --git a/sandbox/policy/win/sandbox_win.h b/sandbox/policy/win/sandbox_win.h
|
|
index 54d808db3a0a2aff198e132fae02c8649a0b547e..e1f5321298e634a310afc10773b93fedbad22431 100644
|
|
--- a/sandbox/policy/win/sandbox_win.h
|
|
+++ b/sandbox/policy/win/sandbox_win.h
|
|
@@ -53,7 +53,7 @@ class SANDBOX_POLICY_EXPORT SandboxWin {
|
|
static ResultCode StartSandboxedProcess(
|
|
const base::CommandLine& cmd_line,
|
|
const std::string& process_type,
|
|
- const base::HandlesToInheritVector& handles_to_inherit,
|
|
+ const base::LaunchOptions* options,
|
|
SandboxDelegate* delegate,
|
|
base::Process* process);
|
|
|
|
@@ -67,7 +67,7 @@ class SANDBOX_POLICY_EXPORT SandboxWin {
|
|
static ResultCode GeneratePolicyForSandboxedProcess(
|
|
const base::CommandLine& cmd_line,
|
|
const std::string& process_type,
|
|
- const base::HandlesToInheritVector& handles_to_inherit,
|
|
+ const base::LaunchOptions* options,
|
|
SandboxDelegate* delegate,
|
|
TargetPolicy* policy);
|
|
|