feat_configure_launch_options_for_service_process.patch 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
  2. From: deepak1556 <[email protected]>
  3. Date: Wed, 17 Aug 2022 22:04:47 +0900
  4. Subject: feat: configure launch options for service process
  5. - POSIX:
  6. Allows configuring base::LaunchOptions::fds_to_remap when launching the child process.
  7. - Win:
  8. Allows configuring base::LaunchOptions::handles_to_inherit, base::LaunchOptions::stdout_handle,
  9. base::LaunchOptions::stderr_handle and base::LaunchOptions::feedback_cursor_off when launching
  10. the child process.
  11. - All:
  12. Allows configuring base::LauncOptions::current_directory, base::LaunchOptions::enviroment
  13. and base::LaunchOptions::clear_environment.
  14. An example use of this option, UtilityProcess API allows reading the output From
  15. stdout and stderr of child process by creating a pipe, whose write end is remapped
  16. to STDOUT_FILENO/STD_OUTPUT_HANDLE and STDERR_FILENO/STD_ERROR_HANDLE allowing the
  17. parent process to read from the pipe.
  18. diff --git a/content/browser/child_process_launcher.h b/content/browser/child_process_launcher.h
  19. index f1773a1ce65e9f4cfe7c39b09d9c523aa804888d..fabe1d524db81135a17203d7637103c691979b39 100644
  20. --- a/content/browser/child_process_launcher.h
  21. +++ b/content/browser/child_process_launcher.h
  22. @@ -33,6 +33,7 @@
  23. #if BUILDFLAG(IS_WIN)
  24. #include "base/win/windows_types.h"
  25. +#include "base/win/scoped_handle.h"
  26. #endif
  27. #if BUILDFLAG(IS_POSIX)
  28. @@ -189,7 +190,10 @@ struct ChildProcessLauncherFileData {
  29. delete;
  30. ~ChildProcessLauncherFileData();
  31. -#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
  32. +#if BUILDFLAG(IS_WIN)
  33. + base::win::ScopedHandle stdout_handle;
  34. + base::win::ScopedHandle stderr_handle;
  35. +#elif BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
  36. // Files opened by the browser and passed as corresponding file descriptors
  37. // in the child process. If a FilePath is provided, the file will be opened
  38. // and the descriptor cached for future process launches. If a ScopedFD is
  39. @@ -204,6 +208,15 @@ struct ChildProcessLauncherFileData {
  40. std::map<std::string, absl::variant<base::FilePath, base::ScopedFD>>
  41. files_to_preload;
  42. #endif
  43. +
  44. +#if BUILDFLAG(IS_POSIX)
  45. + // Map of file descriptors to pass. This is used instead of
  46. + // `files_to_preload` when the data needs to be installed at an exact FD
  47. + // number in the new process.
  48. + //
  49. + // Currently only supported on POSIX platforms.
  50. + std::map<int, base::ScopedFD> additional_remapped_fds;
  51. +#endif
  52. };
  53. // Launches a process asynchronously and notifies the client of the process
  54. diff --git a/content/browser/child_process_launcher_helper_linux.cc b/content/browser/child_process_launcher_helper_linux.cc
  55. index 31a2a14a95540477297943df9b09b1e4659a884d..c02a81b1bd14a300dbbb47ad7aac2d2d7f3bb10f 100644
  56. --- a/content/browser/child_process_launcher_helper_linux.cc
  57. +++ b/content/browser/child_process_launcher_helper_linux.cc
  58. @@ -64,6 +64,11 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
  59. options->fds_to_remap.emplace_back(sandbox_fd, GetSandboxFD());
  60. }
  61. + for (const auto& remapped_fd : file_data_->additional_remapped_fds) {
  62. + options->fds_to_remap.emplace_back(remapped_fd.second.get(),
  63. + remapped_fd.first);
  64. + }
  65. +
  66. // (For Electron), if we're launching without zygote, that means we're
  67. // launching an unsandboxed process (since all sandboxed processes are
  68. // forked from the zygote). Relax the allow_new_privs option to permit
  69. @@ -73,7 +78,9 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
  70. options->allow_new_privs = true;
  71. }
  72. + options->current_directory = delegate_->GetCurrentDirectory();
  73. options->environment = delegate_->GetEnvironment();
  74. + options->clear_environment = !delegate_->ShouldInheritEnvironment();
  75. } else {
  76. DCHECK(GetZygoteForLaunch());
  77. // Environment variables could be supported in the future, but are not
  78. diff --git a/content/browser/child_process_launcher_helper_mac.cc b/content/browser/child_process_launcher_helper_mac.cc
  79. index f1a415f7bd56ece5ab07d2408dbfddf658b45ff3..49bf8f75583cc7b2de415f4ebb42757366a7b51d 100644
  80. --- a/content/browser/child_process_launcher_helper_mac.cc
  81. +++ b/content/browser/child_process_launcher_helper_mac.cc
  82. @@ -110,7 +110,8 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
  83. 'mojo', base::MachRendezvousPort(endpoint.TakeMachReceiveRight())));
  84. options->environment = delegate_->GetEnvironment();
  85. -
  86. + options->clear_environment = !delegate_->ShouldInheritEnvironment();
  87. + options->current_directory = delegate_->GetCurrentDirectory();
  88. options->disclaim_responsibility = delegate_->DisclaimResponsibility();
  89. options->enable_cpu_security_mitigations =
  90. delegate_->EnableCpuSecurityMitigations();
  91. @@ -176,6 +177,11 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
  92. base::StringPrintf("%s%d", sandbox::switches::kSeatbeltClient, pipe));
  93. }
  94. + for (const auto& remapped_fd : file_data_->additional_remapped_fds) {
  95. + options->fds_to_remap.emplace_back(remapped_fd.second.get(),
  96. + remapped_fd.first);
  97. + }
  98. +
  99. return true;
  100. }
  101. diff --git a/content/browser/child_process_launcher_helper_win.cc b/content/browser/child_process_launcher_helper_win.cc
  102. index 2a01487c8ff837357f6d62dba80115b0ec64c343..74343f6a3bfb1eab2aaf1c0b5fba6ceaf9399ef6 100644
  103. --- a/content/browser/child_process_launcher_helper_win.cc
  104. +++ b/content/browser/child_process_launcher_helper_win.cc
  105. @@ -24,6 +24,8 @@
  106. #include "mojo/public/cpp/platform/named_platform_channel.h"
  107. #include "mojo/public/cpp/platform/platform_channel.h"
  108. +#include <windows.h>
  109. +
  110. namespace {
  111. // Helper to avoid marking the log file as non-executable every time we launch a
  112. @@ -132,6 +134,31 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
  113. mojo_channel_->PrepareToPassRemoteEndpoint(&options->handles_to_inherit,
  114. command_line());
  115. }
  116. +
  117. + if (file_data_->stdout_handle.IsValid() || file_data_->stderr_handle.IsValid()) {
  118. + // base::LaunchProcess requires that if any of the stdio handle is customized then
  119. + // the other two handles should also be set.
  120. + // https://source.chromium.org/chromium/chromium/src/+/main:base/process/launch_win.cc;l=341-350
  121. + options->stdin_handle = INVALID_HANDLE_VALUE;
  122. + if (file_data_->stdout_handle.IsValid()) {
  123. + options->stdout_handle = file_data_->stdout_handle.get();
  124. + } else {
  125. + options->stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
  126. + }
  127. +
  128. + if (file_data_->stderr_handle.IsValid()) {
  129. + options->stderr_handle = file_data_->stderr_handle.get();
  130. + } else {
  131. + options->stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
  132. + }
  133. + options->handles_to_inherit.push_back(options->stdout_handle);
  134. + options->handles_to_inherit.push_back(options->stderr_handle);
  135. + }
  136. +
  137. + options->current_directory = delegate_->GetCurrentDirectory();
  138. + options->environment = delegate_->GetEnvironment();
  139. + options->clear_environment = !delegate_->ShouldInheritEnvironment();
  140. + options->feedback_cursor_off = !delegate_->ShouldShowFeedbackCursor();
  141. return true;
  142. }
  143. @@ -159,7 +186,7 @@ ChildProcessLauncherHelper::LaunchProcessOnLauncherThread(
  144. ChildProcessLauncherHelper::Process process;
  145. *launch_result =
  146. StartSandboxedProcess(delegate_.get(), *command_line(),
  147. - options->handles_to_inherit, &process.process);
  148. + options, &process.process);
  149. return process;
  150. }
  151. diff --git a/content/browser/service_process_host_impl.cc b/content/browser/service_process_host_impl.cc
  152. index bdd5bec301f5fcff2d3e3d7994ecbc4eae46da36..f6082bada22c5f4e70af60ea6f555b0f363919c5 100644
  153. --- a/content/browser/service_process_host_impl.cc
  154. +++ b/content/browser/service_process_host_impl.cc
  155. @@ -205,6 +205,17 @@ void LaunchServiceProcess(mojo::GenericPendingReceiver receiver,
  156. options.allow_gpu_client.value()) {
  157. host->SetAllowGpuClient();
  158. }
  159. +
  160. +#if BUILDFLAG(IS_WIN)
  161. + host->SetStdioHandles(std::move(options.stdout_handle), std::move(options.stderr_handle));
  162. + host->SetFeedbackCursorOff(options.feedback_cursor_off);
  163. +#elif BUILDFLAG(IS_POSIX)
  164. + host->SetAdditionalFds(std::move(options.fds_to_remap));
  165. +#endif
  166. + host->SetCurrentDirectory(options.current_directory);
  167. + host->SetEnv(options.environment);
  168. + if (options.clear_environment)
  169. + host->ClearEnvironment();
  170. host->Start();
  171. host->GetChildProcess()->BindServiceInterface(std::move(receiver));
  172. }
  173. diff --git a/content/browser/utility_process_host.cc b/content/browser/utility_process_host.cc
  174. index d63bb20c8a4dc09e3df70cf8fe5b454d593ea360..918d1f92476277cd8f463a7aa1ceda008815c1d7 100644
  175. --- a/content/browser/utility_process_host.cc
  176. +++ b/content/browser/utility_process_host.cc
  177. @@ -179,11 +179,13 @@ const ChildProcessData& UtilityProcessHost::GetData() {
  178. return process_->GetData();
  179. }
  180. -#if BUILDFLAG(IS_POSIX)
  181. void UtilityProcessHost::SetEnv(const base::EnvironmentMap& env) {
  182. env_ = env;
  183. }
  184. -#endif
  185. +
  186. +void UtilityProcessHost::ClearEnvironment() {
  187. + inherit_environment_ = false;
  188. +}
  189. bool UtilityProcessHost::Start() {
  190. return StartProcess();
  191. @@ -230,6 +232,30 @@ void UtilityProcessHost::SetZygoteForTesting(ZygoteCommunication* handle) {
  192. }
  193. #endif // BUILDFLAG(USE_ZYGOTE)
  194. +#if BUILDFLAG(IS_WIN)
  195. +void UtilityProcessHost::SetStdioHandles(
  196. + base::win::ScopedHandle stdout_handle,
  197. + base::win::ScopedHandle stderr_handle) {
  198. + stdout_handle_ = std::move(stdout_handle);
  199. + stderr_handle_ = std::move(stderr_handle);
  200. +}
  201. +#elif BUILDFLAG(IS_POSIX)
  202. +void UtilityProcessHost::SetAdditionalFds(base::FileHandleMappingVector mapping) {
  203. + fds_to_remap_ = std::move(mapping);
  204. +}
  205. +#endif
  206. +
  207. +void UtilityProcessHost::SetCurrentDirectory(
  208. + const base::FilePath& cwd) {
  209. + current_directory_ = cwd;
  210. +}
  211. +
  212. +#if BUILDFLAG(IS_WIN)
  213. +void UtilityProcessHost::SetFeedbackCursorOff(bool feedback_cursor_off) {
  214. + feedback_cursor_off_ = feedback_cursor_off;
  215. +}
  216. +#endif // BUILDFLAG(IS_WIN)
  217. +
  218. mojom::ChildProcess* UtilityProcessHost::GetChildProcess() {
  219. return static_cast<ChildProcessHostImpl*>(process_->GetHost())
  220. ->child_process();
  221. @@ -435,9 +461,26 @@ bool UtilityProcessHost::StartProcess() {
  222. }
  223. #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH)
  224. +#if BUILDFLAG(IS_WIN)
  225. + file_data_->stdout_handle = std::move(stdout_handle_);
  226. + file_data_->stderr_handle = std::move(stderr_handle_);
  227. +#elif BUILDFLAG(IS_POSIX)
  228. + if (!fds_to_remap_.empty()) {
  229. + for (const auto& remapped_fd : fds_to_remap_) {
  230. + file_data_->additional_remapped_fds.emplace(
  231. + remapped_fd.second, remapped_fd.first);
  232. + }
  233. + }
  234. +#endif
  235. +
  236. std::unique_ptr<UtilitySandboxedProcessLauncherDelegate> delegate =
  237. std::make_unique<UtilitySandboxedProcessLauncherDelegate>(
  238. - sandbox_type_, env_, *cmd_line);
  239. + sandbox_type_, env_, current_directory_, *cmd_line,
  240. + inherit_environment_);
  241. +
  242. +#if BUILDFLAG(IS_WIN)
  243. + delegate->SetFeedbackCursorOff(feedback_cursor_off_);
  244. +#endif // BUILDFLAG(IS_WIN)
  245. #if BUILDFLAG(IS_WIN)
  246. if (!preload_libraries_.empty()) {
  247. diff --git a/content/browser/utility_process_host.h b/content/browser/utility_process_host.h
  248. index 9791ae2f761043b9eecd9064a6fd39a6e2339af4..c1809298c830b814f886859c2626d6bce7b9ac8c 100644
  249. --- a/content/browser/utility_process_host.h
  250. +++ b/content/browser/utility_process_host.h
  251. @@ -29,6 +29,10 @@
  252. #include "content/public/common/zygote/zygote_handle.h"
  253. #endif // BUILDFLAG(USE_ZYGOTE)
  254. +#if BUILDFLAG(IS_WIN)
  255. +#include "base/win/scoped_handle.h"
  256. +#endif
  257. +
  258. namespace base {
  259. class Thread;
  260. } // namespace base
  261. @@ -98,9 +102,13 @@ class CONTENT_EXPORT UtilityProcessHost
  262. // Returns information about the utility child process.
  263. const ChildProcessData& GetData();
  264. -#if BUILDFLAG(IS_POSIX)
  265. +
  266. + // Set/Unset environment variables.
  267. void SetEnv(const base::EnvironmentMap& env);
  268. -#endif
  269. +
  270. + // Clear the environment for the new process before processing
  271. + // changes from SetEnv.
  272. + void ClearEnvironment();
  273. // Starts the utility process.
  274. bool Start();
  275. @@ -138,6 +146,21 @@ class CONTENT_EXPORT UtilityProcessHost
  276. void SetZygoteForTesting(ZygoteCommunication* handle);
  277. #endif // BUILDFLAG(USE_ZYGOTE)
  278. +#if BUILDFLAG(IS_WIN)
  279. + void SetStdioHandles(base::win::ScopedHandle stdout_handle,
  280. + base::win::ScopedHandle stderr_handle);
  281. +#elif BUILDFLAG(IS_POSIX)
  282. + void SetAdditionalFds(base::FileHandleMappingVector mapping);
  283. +#endif
  284. +
  285. + // Sets the working directory of the process.
  286. + void SetCurrentDirectory(const base::FilePath& cwd);
  287. +
  288. +#if BUILDFLAG(IS_WIN)
  289. + // Specifies if the process should trigger mouse cursor feedback.
  290. + void SetFeedbackCursorOff(bool feedback_cursor_off);
  291. +#endif // BUILDFLAG(IS_WIN)
  292. +
  293. // Returns a control interface for the running child process.
  294. mojom::ChildProcess* GetChildProcess();
  295. @@ -191,6 +214,27 @@ class CONTENT_EXPORT UtilityProcessHost
  296. std::optional<raw_ptr<ZygoteCommunication>> zygote_for_testing_;
  297. #endif // BUILDFLAG(USE_ZYGOTE)
  298. +#if BUILDFLAG(IS_WIN)
  299. + // Specifies the handles for redirection of stdout and stderr.
  300. + base::win::ScopedHandle stdout_handle_;
  301. + base::win::ScopedHandle stderr_handle_;
  302. +#elif BUILDFLAG(IS_POSIX)
  303. + // Specifies file descriptors to propagate into the child process
  304. + // based on the mapping.
  305. + base::FileHandleMappingVector fds_to_remap_;
  306. +#endif
  307. +
  308. + // If not empty, change to this directory before executing the new process.
  309. + base::FilePath current_directory_;
  310. +
  311. + // Inherit enviroment from parent process.
  312. + bool inherit_environment_ = true;
  313. +
  314. +#if BUILDFLAG(IS_WIN)
  315. + // Specifies if the process should trigger mouse cursor feedback.
  316. + bool feedback_cursor_off_ = false;
  317. +#endif // BUILDFLAG(IS_WIN)
  318. +
  319. // Indicates whether the process has been successfully launched yet, or if
  320. // launch failed.
  321. enum class LaunchState {
  322. diff --git a/content/browser/utility_sandbox_delegate.cc b/content/browser/utility_sandbox_delegate.cc
  323. index ad04359ead729d46d26027a7ef995ebdff1fe842..a476a4c1be9156270c8400666f4042de584555ca 100644
  324. --- a/content/browser/utility_sandbox_delegate.cc
  325. +++ b/content/browser/utility_sandbox_delegate.cc
  326. @@ -34,17 +34,19 @@ UtilitySandboxedProcessLauncherDelegate::
  327. UtilitySandboxedProcessLauncherDelegate(
  328. sandbox::mojom::Sandbox sandbox_type,
  329. const base::EnvironmentMap& env,
  330. - const base::CommandLine& cmd_line)
  331. + const base::FilePath& cwd,
  332. + const base::CommandLine& cmd_line,
  333. + bool inherit_environment)
  334. :
  335. -#if BUILDFLAG(IS_POSIX)
  336. env_(env),
  337. -#endif
  338. + current_directory_(cwd),
  339. sandbox_type_(sandbox_type),
  340. #if BUILDFLAG(IS_WIN)
  341. app_container_disabled_(
  342. GetContentClient()->browser()->IsAppContainerDisabled(sandbox_type)),
  343. #endif
  344. - cmd_line_(cmd_line) {
  345. + cmd_line_(cmd_line),
  346. + inherit_environment_(inherit_environment) {
  347. #if DCHECK_IS_ON()
  348. bool supported_sandbox_type =
  349. sandbox_type_ == sandbox::mojom::Sandbox::kNoSandbox ||
  350. @@ -110,11 +112,28 @@ UtilitySandboxedProcessLauncherDelegate::GetSandboxType() {
  351. return sandbox_type_;
  352. }
  353. -#if BUILDFLAG(IS_POSIX)
  354. base::EnvironmentMap UtilitySandboxedProcessLauncherDelegate::GetEnvironment() {
  355. return env_;
  356. }
  357. -#endif // BUILDFLAG(IS_POSIX)
  358. +
  359. +bool UtilitySandboxedProcessLauncherDelegate::ShouldInheritEnvironment() {
  360. + return inherit_environment_;
  361. +}
  362. +
  363. +base::FilePath UtilitySandboxedProcessLauncherDelegate::GetCurrentDirectory() {
  364. + return current_directory_;
  365. +}
  366. +
  367. +#if BUILDFLAG(IS_WIN)
  368. +void UtilitySandboxedProcessLauncherDelegate::SetFeedbackCursorOff(
  369. + bool feedback_cursor_off) {
  370. + feedback_cursor_off_ = feedback_cursor_off;
  371. +}
  372. +
  373. +bool UtilitySandboxedProcessLauncherDelegate::ShouldShowFeedbackCursor() {
  374. + return !feedback_cursor_off_;
  375. +}
  376. +#endif // BUILDFLAG(IS_WIN)
  377. #if BUILDFLAG(USE_ZYGOTE)
  378. ZygoteCommunication* UtilitySandboxedProcessLauncherDelegate::GetZygote() {
  379. diff --git a/content/browser/utility_sandbox_delegate.h b/content/browser/utility_sandbox_delegate.h
  380. index 27cef06ded34680c6bfa3e954924de645a1b8217..7c114956a77da7b60526dd93593d84627356bb16 100644
  381. --- a/content/browser/utility_sandbox_delegate.h
  382. +++ b/content/browser/utility_sandbox_delegate.h
  383. @@ -30,7 +30,9 @@ class CONTENT_EXPORT UtilitySandboxedProcessLauncherDelegate
  384. public:
  385. UtilitySandboxedProcessLauncherDelegate(sandbox::mojom::Sandbox sandbox_type,
  386. const base::EnvironmentMap& env,
  387. - const base::CommandLine& cmd_line);
  388. + const base::FilePath& cwd,
  389. + const base::CommandLine& cmd_line,
  390. + bool inherit_environment);
  391. ~UtilitySandboxedProcessLauncherDelegate() override;
  392. sandbox::mojom::Sandbox GetSandboxType() override;
  393. @@ -55,18 +57,21 @@ class CONTENT_EXPORT UtilitySandboxedProcessLauncherDelegate
  394. ZygoteCommunication* GetZygote() override;
  395. #endif // BUILDFLAG(USE_ZYGOTE)
  396. -#if BUILDFLAG(IS_POSIX)
  397. base::EnvironmentMap GetEnvironment() override;
  398. -#endif // BUILDFLAG(IS_POSIX)
  399. + bool ShouldInheritEnvironment() override;
  400. + base::FilePath GetCurrentDirectory() override;
  401. +
  402. +#if BUILDFLAG(IS_WIN)
  403. + void SetFeedbackCursorOff(bool feedback_cursor_off);
  404. + bool ShouldShowFeedbackCursor() override;
  405. +#endif // BUILDFLAG(IS_WIN)
  406. #if BUILDFLAG(USE_ZYGOTE)
  407. void SetZygote(ZygoteCommunication* handle);
  408. #endif // BUILDFLAG(USE_ZYGOTE_HANDLE)
  409. private:
  410. -#if BUILDFLAG(IS_POSIX)
  411. base::EnvironmentMap env_;
  412. -#endif // BUILDFLAG(IS_POSIX)
  413. #if BUILDFLAG(IS_WIN)
  414. std::vector<base::FilePath> preload_libraries_;
  415. @@ -76,12 +81,17 @@ class CONTENT_EXPORT UtilitySandboxedProcessLauncherDelegate
  416. std::optional<raw_ptr<ZygoteCommunication>> zygote_;
  417. #endif // BUILDFLAG(USE_ZYGOTE)
  418. + base::FilePath current_directory_;
  419. const sandbox::mojom::Sandbox sandbox_type_;
  420. #if BUILDFLAG(IS_WIN)
  421. // If true then App Container will not be used for this utility process.
  422. const bool app_container_disabled_;
  423. #endif // BUILDFLAG(IS_WIN)
  424. base::CommandLine cmd_line_;
  425. + bool inherit_environment_;
  426. +#if BUILDFLAG(IS_WIN)
  427. + bool feedback_cursor_off_ = false;
  428. +#endif // BUILDFLAG(IS_WIN)
  429. };
  430. } // namespace content
  431. diff --git a/content/common/sandbox_init_win.cc b/content/common/sandbox_init_win.cc
  432. index b96d6a879e8b6664559bac69f726321fdb02b40f..bfeec6ddb98d4127c1dcfe5999894f1cdebdc087 100644
  433. --- a/content/common/sandbox_init_win.cc
  434. +++ b/content/common/sandbox_init_win.cc
  435. @@ -23,7 +23,7 @@ namespace content {
  436. sandbox::ResultCode StartSandboxedProcess(
  437. SandboxedProcessLauncherDelegate* delegate,
  438. const base::CommandLine& target_command_line,
  439. - const base::HandlesToInheritVector& handles_to_inherit,
  440. + const base::LaunchOptions* options,
  441. base::Process* process) {
  442. std::string type_str =
  443. target_command_line.GetSwitchValueASCII(switches::kProcessType);
  444. @@ -45,7 +45,7 @@ sandbox::ResultCode StartSandboxedProcess(
  445. }
  446. return sandbox::policy::SandboxWin::StartSandboxedProcess(
  447. - full_command_line, handles_to_inherit, delegate, process);
  448. + full_command_line, options, delegate, process);
  449. }
  450. } // namespace content
  451. diff --git a/content/public/browser/service_process_host.cc b/content/public/browser/service_process_host.cc
  452. index 8defae52a201a97c402e304216ce772a717a9f7e..4aee78366398c018e315ef15e631d0792ee79c47 100644
  453. --- a/content/public/browser/service_process_host.cc
  454. +++ b/content/public/browser/service_process_host.cc
  455. @@ -52,12 +52,53 @@ ServiceProcessHost::Options::WithExtraCommandLineSwitches(
  456. return *this;
  457. }
  458. +#if BUILDFLAG(IS_WIN)
  459. +ServiceProcessHost::Options& ServiceProcessHost::Options::WithStdoutHandle(
  460. + base::win::ScopedHandle handle) {
  461. + stdout_handle = std::move(handle);
  462. + return *this;
  463. +}
  464. +
  465. +ServiceProcessHost::Options& ServiceProcessHost::Options::WithStderrHandle(
  466. + base::win::ScopedHandle handle) {
  467. + stderr_handle = std::move(handle);
  468. + return *this;
  469. +}
  470. +#elif BUILDFLAG(IS_POSIX)
  471. +ServiceProcessHost::Options& ServiceProcessHost::Options::WithAdditionalFds(
  472. + base::FileHandleMappingVector mapping) {
  473. + fds_to_remap = std::move(mapping);
  474. + return *this;
  475. +}
  476. +#endif
  477. +
  478. ServiceProcessHost::Options& ServiceProcessHost::Options::WithProcessCallback(
  479. base::OnceCallback<void(const base::Process&)> callback) {
  480. process_callback = std::move(callback);
  481. return *this;
  482. }
  483. +ServiceProcessHost::Options& ServiceProcessHost::Options::WithCurrentDirectory(
  484. + const base::FilePath& cwd) {
  485. + current_directory = cwd;
  486. + return *this;
  487. +}
  488. +
  489. +ServiceProcessHost::Options& ServiceProcessHost::Options::WithEnvironment(
  490. + const base::EnvironmentMap& env, bool new_environment) {
  491. + environment = env;
  492. + clear_environment = new_environment;
  493. + return *this;
  494. +}
  495. +
  496. +#if BUILDFLAG(IS_WIN)
  497. +ServiceProcessHost::Options& ServiceProcessHost::Options::WithFeedbackCursorOff(
  498. + bool turn_feedback_cursor_off) {
  499. + feedback_cursor_off = turn_feedback_cursor_off;
  500. + return *this;
  501. +}
  502. +#endif // #if BUILDFLAG(IS_WIN)
  503. +
  504. #if BUILDFLAG(IS_WIN)
  505. ServiceProcessHost::Options&
  506. ServiceProcessHost::Options::WithPreloadedLibraries(
  507. diff --git a/content/public/browser/service_process_host.h b/content/public/browser/service_process_host.h
  508. index 0062d2cb6634b8b29977a0312516b1b13936b40a..611a52e908f4cb70fbe5628e220a082e45320b70 100644
  509. --- a/content/public/browser/service_process_host.h
  510. +++ b/content/public/browser/service_process_host.h
  511. @@ -14,6 +14,7 @@
  512. #include "base/command_line.h"
  513. #include "base/functional/callback.h"
  514. #include "base/observer_list_types.h"
  515. +#include "base/process/launch.h"
  516. #include "base/process/process_handle.h"
  517. #include "content/common/content_export.h"
  518. #include "content/public/browser/service_process_info.h"
  519. @@ -28,6 +29,10 @@
  520. #include "base/types/pass_key.h"
  521. #endif // BUILDFLAG(IS_WIN)
  522. +#if BUILDFLAG(IS_WIN)
  523. +#include "base/win/scoped_handle.h"
  524. +#endif
  525. +
  526. namespace base {
  527. class Process;
  528. } // namespace base
  529. @@ -94,11 +99,35 @@ class CONTENT_EXPORT ServiceProcessHost {
  530. // Specifies extra command line switches to append before launch.
  531. Options& WithExtraCommandLineSwitches(std::vector<std::string> switches);
  532. +#if BUILDFLAG(IS_WIN)
  533. + // Specifies the handles for redirection of stdout and stderr.
  534. + Options& WithStdoutHandle(base::win::ScopedHandle stdout_handle);
  535. + Options& WithStderrHandle(base::win::ScopedHandle stderr_handle);
  536. +#elif BUILDFLAG(IS_POSIX)
  537. + // Specifies file descriptors to propagate into the child process
  538. + // based on the mapping.
  539. + Options& WithAdditionalFds(base::FileHandleMappingVector mapping);
  540. +#endif
  541. +
  542. // Specifies a callback to be invoked with service process once it's
  543. // launched. Will be on UI thread.
  544. Options& WithProcessCallback(
  545. base::OnceCallback<void(const base::Process&)>);
  546. + // Specifies the working directory for the launched process.
  547. + Options& WithCurrentDirectory(const base::FilePath& cwd);
  548. +
  549. + // Specifies the environment that should be applied to the process.
  550. + // |new_environment| controls whether the process should inherit
  551. + // environment from the parent process.
  552. + Options& WithEnvironment(const base::EnvironmentMap& environment,
  553. + bool new_environment);
  554. +
  555. +#if BUILDFLAG(IS_WIN)
  556. + // Specifies if the process should trigger mouse cursor feedback.
  557. + Options& WithFeedbackCursorOff(bool feedback_cursor_off);
  558. +#endif // #if BUILDFLAG(IS_WIN)
  559. +
  560. #if BUILDFLAG(IS_WIN)
  561. // Specifies libraries to preload before the sandbox is locked down. Paths
  562. // should be absolute paths. Libraries will be preloaded before sandbox
  563. @@ -127,11 +156,23 @@ class CONTENT_EXPORT ServiceProcessHost {
  564. std::optional<GURL> site;
  565. std::optional<int> child_flags;
  566. std::vector<std::string> extra_switches;
  567. +#if BUILDFLAG(IS_WIN)
  568. + base::win::ScopedHandle stdout_handle;
  569. + base::win::ScopedHandle stderr_handle;
  570. +#elif BUILDFLAG(IS_POSIX)
  571. + base::FileHandleMappingVector fds_to_remap;
  572. +#endif
  573. base::OnceCallback<void(const base::Process&)> process_callback;
  574. #if BUILDFLAG(IS_WIN)
  575. std::vector<base::FilePath> preload_libraries;
  576. #endif // BUILDFLAG(IS_WIN)
  577. std::optional<bool> allow_gpu_client;
  578. + base::FilePath current_directory;
  579. + base::EnvironmentMap environment;
  580. + bool clear_environment = false;
  581. +#if BUILDFLAG(IS_WIN)
  582. + bool feedback_cursor_off = false;
  583. +#endif // BUILDFLAG(IS_WIN)
  584. };
  585. // An interface which can be implemented and registered/unregistered with
  586. diff --git a/content/public/common/sandbox_init_win.h b/content/public/common/sandbox_init_win.h
  587. index 9bb4b30ba0f5d37ec2b28f0848d94f34c24f9423..b614fef01ee5cdf81b7112be721b851c454756a2 100644
  588. --- a/content/public/common/sandbox_init_win.h
  589. +++ b/content/public/common/sandbox_init_win.h
  590. @@ -29,7 +29,7 @@ class SandboxedProcessLauncherDelegate;
  591. CONTENT_EXPORT sandbox::ResultCode StartSandboxedProcess(
  592. SandboxedProcessLauncherDelegate* delegate,
  593. const base::CommandLine& target_command_line,
  594. - const base::HandlesToInheritVector& handles_to_inherit,
  595. + const base::LaunchOptions* options,
  596. base::Process* process);
  597. } // namespace content
  598. diff --git a/content/public/common/sandboxed_process_launcher_delegate.cc b/content/public/common/sandboxed_process_launcher_delegate.cc
  599. index 9c1aa450f32b6812d4a87cd0b9ee0dfb1a9557f4..c281fc33709376dbd50af281c219f3f5bda5635b 100644
  600. --- a/content/public/common/sandboxed_process_launcher_delegate.cc
  601. +++ b/content/public/common/sandboxed_process_launcher_delegate.cc
  602. @@ -68,11 +68,23 @@ ZygoteCommunication* SandboxedProcessLauncherDelegate::GetZygote() {
  603. }
  604. #endif // BUILDFLAG(USE_ZYGOTE)
  605. -#if BUILDFLAG(IS_POSIX)
  606. base::EnvironmentMap SandboxedProcessLauncherDelegate::GetEnvironment() {
  607. return base::EnvironmentMap();
  608. }
  609. -#endif // BUILDFLAG(IS_POSIX)
  610. +
  611. +bool SandboxedProcessLauncherDelegate::ShouldInheritEnvironment() {
  612. + return true;
  613. +}
  614. +
  615. +base::FilePath SandboxedProcessLauncherDelegate::GetCurrentDirectory() {
  616. + return base::FilePath();
  617. +}
  618. +
  619. +#if BUILDFLAG(IS_WIN)
  620. +bool SandboxedProcessLauncherDelegate::ShouldShowFeedbackCursor() {
  621. + return true;
  622. +}
  623. +#endif // #if BUILDFLAG(IS_WIN)
  624. #if BUILDFLAG(IS_MAC)
  625. diff --git a/content/public/common/sandboxed_process_launcher_delegate.h b/content/public/common/sandboxed_process_launcher_delegate.h
  626. index cb43aa14c9742f3788ae58c3e49b890cd532f327..276b2a06fabba559eb1caaaa9129b9f78058aa9f 100644
  627. --- a/content/public/common/sandboxed_process_launcher_delegate.h
  628. +++ b/content/public/common/sandboxed_process_launcher_delegate.h
  629. @@ -6,6 +6,7 @@
  630. #define CONTENT_PUBLIC_COMMON_SANDBOXED_PROCESS_LAUNCHER_DELEGATE_H_
  631. #include "base/environment.h"
  632. +#include "base/files/file_path.h"
  633. #include "base/files/scoped_file.h"
  634. #include "base/process/process.h"
  635. #include "build/build_config.h"
  636. @@ -57,10 +58,19 @@ class CONTENT_EXPORT SandboxedProcessLauncherDelegate
  637. virtual ZygoteCommunication* GetZygote();
  638. #endif // BUILDFLAG(USE_ZYGOTE)
  639. -#if BUILDFLAG(IS_POSIX)
  640. // Override this if the process needs a non-empty environment map.
  641. virtual base::EnvironmentMap GetEnvironment();
  642. -#endif // BUILDFLAG(IS_POSIX)
  643. +
  644. + // Override this if the process should not inherit parent environment.
  645. + virtual bool ShouldInheritEnvironment();
  646. +
  647. + // Specifies the directory to change to before executing the process.
  648. + virtual base::FilePath GetCurrentDirectory();
  649. +
  650. +#if BUILDFLAG(IS_WIN)
  651. + // Override this if the process should not trigger mouse cursor feedback.
  652. + virtual bool ShouldShowFeedbackCursor();
  653. +#endif // #if BUILDFLAG(IS_WIN)
  654. #if BUILDFLAG(IS_MAC)
  655. // Whether or not to disclaim TCC responsibility for the process, defaults to
  656. diff --git a/sandbox/policy/win/sandbox_win.cc b/sandbox/policy/win/sandbox_win.cc
  657. index aecdbe31e3ddcc66798c11902a415c767679c233..904520a77541c9bfd4b2ba31df830af3f588269e 100644
  658. --- a/sandbox/policy/win/sandbox_win.cc
  659. +++ b/sandbox/policy/win/sandbox_win.cc
  660. @@ -700,11 +700,9 @@ base::win::ScopedHandle CreateUnsandboxedJob() {
  661. // command line flag.
  662. ResultCode LaunchWithoutSandbox(
  663. const base::CommandLine& cmd_line,
  664. - const base::HandlesToInheritVector& handles_to_inherit,
  665. + base::LaunchOptions options,
  666. SandboxDelegate* delegate,
  667. base::Process* process) {
  668. - base::LaunchOptions options;
  669. - options.handles_to_inherit = handles_to_inherit;
  670. // Network process runs in a job even when unsandboxed. This is to ensure it
  671. // does not outlive the browser, which could happen if there is a lot of I/O
  672. // on process shutdown, in which case TerminateProcess can fail. See
  673. @@ -934,7 +932,7 @@ bool SandboxWin::InitTargetServices(TargetServices* target_services) {
  674. // static
  675. ResultCode SandboxWin::GeneratePolicyForSandboxedProcess(
  676. const base::CommandLine& cmd_line,
  677. - const base::HandlesToInheritVector& handles_to_inherit,
  678. + const base::LaunchOptions* options,
  679. SandboxDelegate* delegate,
  680. TargetPolicy* policy) {
  681. const base::CommandLine& launcher_process_command_line =
  682. @@ -948,7 +946,7 @@ ResultCode SandboxWin::GeneratePolicyForSandboxedProcess(
  683. }
  684. // Add any handles to be inherited to the policy.
  685. - for (HANDLE handle : handles_to_inherit)
  686. + for (HANDLE handle : options->handles_to_inherit)
  687. policy->AddHandleToShare(handle);
  688. if (!policy->GetConfig()->IsConfigured()) {
  689. @@ -963,6 +961,13 @@ ResultCode SandboxWin::GeneratePolicyForSandboxedProcess(
  690. // have no effect. These calls can fail with SBOX_ERROR_BAD_PARAMS.
  691. policy->SetStdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE));
  692. policy->SetStderrHandle(GetStdHandle(STD_ERROR_HANDLE));
  693. +#else
  694. + if (options->stdout_handle != nullptr && options->stdout_handle != INVALID_HANDLE_VALUE) {
  695. + policy->SetStdoutHandle(options->stdout_handle);
  696. + }
  697. + if (options->stderr_handle != nullptr && options->stderr_handle != INVALID_HANDLE_VALUE) {
  698. + policy->SetStderrHandle(options->stderr_handle);
  699. + }
  700. #endif
  701. if (!delegate->PreSpawnTarget(policy))
  702. @@ -974,7 +979,7 @@ ResultCode SandboxWin::GeneratePolicyForSandboxedProcess(
  703. // static
  704. ResultCode SandboxWin::StartSandboxedProcess(
  705. const base::CommandLine& cmd_line,
  706. - const base::HandlesToInheritVector& handles_to_inherit,
  707. + const base::LaunchOptions* options,
  708. SandboxDelegate* delegate,
  709. base::Process* process) {
  710. SandboxLaunchTimer timer;
  711. @@ -982,7 +987,7 @@ ResultCode SandboxWin::StartSandboxedProcess(
  712. // Avoid making a policy if we won't use it.
  713. if (IsUnsandboxedProcess(delegate->GetSandboxType(), cmd_line,
  714. *base::CommandLine::ForCurrentProcess())) {
  715. - return LaunchWithoutSandbox(cmd_line, handles_to_inherit, delegate,
  716. + return LaunchWithoutSandbox(cmd_line, *options, delegate,
  717. process);
  718. }
  719. @@ -990,7 +995,7 @@ ResultCode SandboxWin::StartSandboxedProcess(
  720. timer.OnPolicyCreated();
  721. ResultCode result = GeneratePolicyForSandboxedProcess(
  722. - cmd_line, handles_to_inherit, delegate, policy.get());
  723. + cmd_line, options, delegate, policy.get());
  724. if (SBOX_ALL_OK != result)
  725. return result;
  726. timer.OnPolicyGenerated();
  727. diff --git a/sandbox/policy/win/sandbox_win.h b/sandbox/policy/win/sandbox_win.h
  728. index 271e80f52b15484ecc8b31b12b012eac39b3d333..cd3d803f52972c4ae8af6a0411b5be0e0a5bc782 100644
  729. --- a/sandbox/policy/win/sandbox_win.h
  730. +++ b/sandbox/policy/win/sandbox_win.h
  731. @@ -52,7 +52,7 @@ class SANDBOX_POLICY_EXPORT SandboxWin {
  732. // Otherwise, returns one of sandbox::ResultCode for any other error.
  733. static ResultCode StartSandboxedProcess(
  734. const base::CommandLine& cmd_line,
  735. - const base::HandlesToInheritVector& handles_to_inherit,
  736. + const base::LaunchOptions* options,
  737. SandboxDelegate* delegate,
  738. base::Process* process);
  739. @@ -65,7 +65,7 @@ class SANDBOX_POLICY_EXPORT SandboxWin {
  740. // of sandbox::ResultCode for any other error while constructing the policy.
  741. static ResultCode GeneratePolicyForSandboxedProcess(
  742. const base::CommandLine& cmd_line,
  743. - const base::HandlesToInheritVector& handles_to_inherit,
  744. + const base::LaunchOptions* options,
  745. SandboxDelegate* delegate,
  746. TargetPolicy* policy);