feat_configure_launch_options_for_service_process.patch 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805
  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 572f23d579c0bce81b4b63f7030297d469ef3fbd..5a6ce0a7888f449ad73c6870bab569df7a23bd80 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. @@ -177,6 +178,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 cb0e7d5c5dc0154c6e88ad08ce097afdce4041f9..09b9cff76d9585297fe60f91970c610ac445f06a 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. @@ -158,7 +185,7 @@ ChildProcessLauncherHelper::LaunchProcessOnLauncherThread(
  144. }
  145. *is_synchronous_launch = false;
  146. *launch_result = StartSandboxedProcess(
  147. - delegate_.get(), *command_line(), options->handles_to_inherit,
  148. + delegate_.get(), *command_line(), options,
  149. base::BindOnce(&ChildProcessLauncherHelper::
  150. FinishStartSandboxedProcessOnLauncherThread,
  151. this));
  152. diff --git a/content/browser/service_process_host_impl.cc b/content/browser/service_process_host_impl.cc
  153. index bdd5bec301f5fcff2d3e3d7994ecbc4eae46da36..f6082bada22c5f4e70af60ea6f555b0f363919c5 100644
  154. --- a/content/browser/service_process_host_impl.cc
  155. +++ b/content/browser/service_process_host_impl.cc
  156. @@ -205,6 +205,17 @@ void LaunchServiceProcess(mojo::GenericPendingReceiver receiver,
  157. options.allow_gpu_client.value()) {
  158. host->SetAllowGpuClient();
  159. }
  160. +
  161. +#if BUILDFLAG(IS_WIN)
  162. + host->SetStdioHandles(std::move(options.stdout_handle), std::move(options.stderr_handle));
  163. + host->SetFeedbackCursorOff(options.feedback_cursor_off);
  164. +#elif BUILDFLAG(IS_POSIX)
  165. + host->SetAdditionalFds(std::move(options.fds_to_remap));
  166. +#endif
  167. + host->SetCurrentDirectory(options.current_directory);
  168. + host->SetEnv(options.environment);
  169. + if (options.clear_environment)
  170. + host->ClearEnvironment();
  171. host->Start();
  172. host->GetChildProcess()->BindServiceInterface(std::move(receiver));
  173. }
  174. diff --git a/content/browser/utility_process_host.cc b/content/browser/utility_process_host.cc
  175. index 605117f78bb9ad2f8f2b04ca398c78a88f5b8243..d49b7f0c0026bb1159f92a93db32adee4b4883ca 100644
  176. --- a/content/browser/utility_process_host.cc
  177. +++ b/content/browser/utility_process_host.cc
  178. @@ -181,11 +181,13 @@ const ChildProcessData& UtilityProcessHost::GetData() {
  179. return process_->GetData();
  180. }
  181. -#if BUILDFLAG(IS_POSIX)
  182. void UtilityProcessHost::SetEnv(const base::EnvironmentMap& env) {
  183. env_ = env;
  184. }
  185. -#endif
  186. +
  187. +void UtilityProcessHost::ClearEnvironment() {
  188. + inherit_environment_ = false;
  189. +}
  190. bool UtilityProcessHost::Start() {
  191. return StartProcess();
  192. @@ -233,6 +235,30 @@ void UtilityProcessHost::SetZygoteForTesting(ZygoteCommunication* handle) {
  193. }
  194. #endif // BUILDFLAG(USE_ZYGOTE)
  195. +#if BUILDFLAG(IS_WIN)
  196. +void UtilityProcessHost::SetStdioHandles(
  197. + base::win::ScopedHandle stdout_handle,
  198. + base::win::ScopedHandle stderr_handle) {
  199. + stdout_handle_ = std::move(stdout_handle);
  200. + stderr_handle_ = std::move(stderr_handle);
  201. +}
  202. +#elif BUILDFLAG(IS_POSIX)
  203. +void UtilityProcessHost::SetAdditionalFds(base::FileHandleMappingVector mapping) {
  204. + fds_to_remap_ = std::move(mapping);
  205. +}
  206. +#endif
  207. +
  208. +void UtilityProcessHost::SetCurrentDirectory(
  209. + const base::FilePath& cwd) {
  210. + current_directory_ = cwd;
  211. +}
  212. +
  213. +#if BUILDFLAG(IS_WIN)
  214. +void UtilityProcessHost::SetFeedbackCursorOff(bool feedback_cursor_off) {
  215. + feedback_cursor_off_ = feedback_cursor_off;
  216. +}
  217. +#endif // BUILDFLAG(IS_WIN)
  218. +
  219. mojom::ChildProcess* UtilityProcessHost::GetChildProcess() {
  220. return static_cast<ChildProcessHostImpl*>(process_->GetHost())
  221. ->child_process();
  222. @@ -437,9 +463,26 @@ bool UtilityProcessHost::StartProcess() {
  223. #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH) ||
  224. // BUILDFLAG(IS_MAC)
  225. +#if BUILDFLAG(IS_WIN)
  226. + file_data_->stdout_handle = std::move(stdout_handle_);
  227. + file_data_->stderr_handle = std::move(stderr_handle_);
  228. +#elif BUILDFLAG(IS_POSIX)
  229. + if (!fds_to_remap_.empty()) {
  230. + for (const auto& remapped_fd : fds_to_remap_) {
  231. + file_data_->additional_remapped_fds.emplace(
  232. + remapped_fd.second, remapped_fd.first);
  233. + }
  234. + }
  235. +#endif
  236. +
  237. std::unique_ptr<UtilitySandboxedProcessLauncherDelegate> delegate =
  238. std::make_unique<UtilitySandboxedProcessLauncherDelegate>(
  239. - sandbox_type_, env_, *cmd_line);
  240. + sandbox_type_, env_, current_directory_, *cmd_line,
  241. + inherit_environment_);
  242. +
  243. +#if BUILDFLAG(IS_WIN)
  244. + delegate->SetFeedbackCursorOff(feedback_cursor_off_);
  245. +#endif // BUILDFLAG(IS_WIN)
  246. #if BUILDFLAG(IS_WIN)
  247. if (!preload_libraries_.empty()) {
  248. diff --git a/content/browser/utility_process_host.h b/content/browser/utility_process_host.h
  249. index faa41e5f2571f7a8aa4eef927eca003801d787f6..16d5efc5f9191020aa2180d665cf520748a62a8f 100644
  250. --- a/content/browser/utility_process_host.h
  251. +++ b/content/browser/utility_process_host.h
  252. @@ -29,6 +29,10 @@
  253. #include "content/public/common/zygote/zygote_handle.h"
  254. #endif // BUILDFLAG(USE_ZYGOTE)
  255. +#if BUILDFLAG(IS_WIN)
  256. +#include "base/win/scoped_handle.h"
  257. +#endif
  258. +
  259. namespace base {
  260. class Thread;
  261. } // namespace base
  262. @@ -99,9 +103,13 @@ class CONTENT_EXPORT UtilityProcessHost
  263. // Returns information about the utility child process.
  264. const ChildProcessData& GetData();
  265. -#if BUILDFLAG(IS_POSIX)
  266. +
  267. + // Set/Unset environment variables.
  268. void SetEnv(const base::EnvironmentMap& env);
  269. -#endif
  270. +
  271. + // Clear the environment for the new process before processing
  272. + // changes from SetEnv.
  273. + void ClearEnvironment();
  274. // Starts the utility process.
  275. bool Start();
  276. @@ -139,6 +147,21 @@ class CONTENT_EXPORT UtilityProcessHost
  277. void SetZygoteForTesting(ZygoteCommunication* handle);
  278. #endif // BUILDFLAG(USE_ZYGOTE)
  279. +#if BUILDFLAG(IS_WIN)
  280. + void SetStdioHandles(base::win::ScopedHandle stdout_handle,
  281. + base::win::ScopedHandle stderr_handle);
  282. +#elif BUILDFLAG(IS_POSIX)
  283. + void SetAdditionalFds(base::FileHandleMappingVector mapping);
  284. +#endif
  285. +
  286. + // Sets the working directory of the process.
  287. + void SetCurrentDirectory(const base::FilePath& cwd);
  288. +
  289. +#if BUILDFLAG(IS_WIN)
  290. + // Specifies if the process should trigger mouse cursor feedback.
  291. + void SetFeedbackCursorOff(bool feedback_cursor_off);
  292. +#endif // BUILDFLAG(IS_WIN)
  293. +
  294. // Returns a control interface for the running child process.
  295. mojom::ChildProcess* GetChildProcess();
  296. @@ -192,6 +215,27 @@ class CONTENT_EXPORT UtilityProcessHost
  297. std::optional<raw_ptr<ZygoteCommunication>> zygote_for_testing_;
  298. #endif // BUILDFLAG(USE_ZYGOTE)
  299. +#if BUILDFLAG(IS_WIN)
  300. + // Specifies the handles for redirection of stdout and stderr.
  301. + base::win::ScopedHandle stdout_handle_;
  302. + base::win::ScopedHandle stderr_handle_;
  303. +#elif BUILDFLAG(IS_POSIX)
  304. + // Specifies file descriptors to propagate into the child process
  305. + // based on the mapping.
  306. + base::FileHandleMappingVector fds_to_remap_;
  307. +#endif
  308. +
  309. + // If not empty, change to this directory before executing the new process.
  310. + base::FilePath current_directory_;
  311. +
  312. + // Inherit enviroment from parent process.
  313. + bool inherit_environment_ = true;
  314. +
  315. +#if BUILDFLAG(IS_WIN)
  316. + // Specifies if the process should trigger mouse cursor feedback.
  317. + bool feedback_cursor_off_ = false;
  318. +#endif // BUILDFLAG(IS_WIN)
  319. +
  320. // Indicates whether the process has been successfully launched yet, or if
  321. // launch failed.
  322. enum class LaunchState {
  323. diff --git a/content/browser/utility_sandbox_delegate.cc b/content/browser/utility_sandbox_delegate.cc
  324. index 87bff385e6893206aedb9bbf108254056b4e93a7..e845a03fb69ff5997c0facc0bacdfcc3df0e0bdb 100644
  325. --- a/content/browser/utility_sandbox_delegate.cc
  326. +++ b/content/browser/utility_sandbox_delegate.cc
  327. @@ -41,17 +41,19 @@ UtilitySandboxedProcessLauncherDelegate::
  328. UtilitySandboxedProcessLauncherDelegate(
  329. sandbox::mojom::Sandbox sandbox_type,
  330. const base::EnvironmentMap& env,
  331. - const base::CommandLine& cmd_line)
  332. + const base::FilePath& cwd,
  333. + const base::CommandLine& cmd_line,
  334. + bool inherit_environment)
  335. :
  336. -#if BUILDFLAG(IS_POSIX)
  337. env_(env),
  338. -#endif
  339. + current_directory_(cwd),
  340. sandbox_type_(sandbox_type),
  341. #if BUILDFLAG(IS_WIN)
  342. app_container_disabled_(
  343. GetContentClient()->browser()->IsAppContainerDisabled(sandbox_type)),
  344. #endif
  345. - cmd_line_(cmd_line) {
  346. + cmd_line_(cmd_line),
  347. + inherit_environment_(inherit_environment) {
  348. #if DCHECK_IS_ON()
  349. bool supported_sandbox_type =
  350. sandbox_type_ == sandbox::mojom::Sandbox::kNoSandbox ||
  351. @@ -120,11 +122,28 @@ UtilitySandboxedProcessLauncherDelegate::GetSandboxType() {
  352. return sandbox_type_;
  353. }
  354. -#if BUILDFLAG(IS_POSIX)
  355. base::EnvironmentMap UtilitySandboxedProcessLauncherDelegate::GetEnvironment() {
  356. return env_;
  357. }
  358. -#endif // BUILDFLAG(IS_POSIX)
  359. +
  360. +bool UtilitySandboxedProcessLauncherDelegate::ShouldInheritEnvironment() {
  361. + return inherit_environment_;
  362. +}
  363. +
  364. +base::FilePath UtilitySandboxedProcessLauncherDelegate::GetCurrentDirectory() {
  365. + return current_directory_;
  366. +}
  367. +
  368. +#if BUILDFLAG(IS_WIN)
  369. +void UtilitySandboxedProcessLauncherDelegate::SetFeedbackCursorOff(
  370. + bool feedback_cursor_off) {
  371. + feedback_cursor_off_ = feedback_cursor_off;
  372. +}
  373. +
  374. +bool UtilitySandboxedProcessLauncherDelegate::ShouldShowFeedbackCursor() {
  375. + return !feedback_cursor_off_;
  376. +}
  377. +#endif // BUILDFLAG(IS_WIN)
  378. #if BUILDFLAG(USE_ZYGOTE)
  379. ZygoteCommunication* UtilitySandboxedProcessLauncherDelegate::GetZygote() {
  380. diff --git a/content/browser/utility_sandbox_delegate.h b/content/browser/utility_sandbox_delegate.h
  381. index f3167c642c1f594c29ef7aa2a92a246f1d045344..f1f1dc8082b6039bf119ce10e7e4ca0e941d4cbd 100644
  382. --- a/content/browser/utility_sandbox_delegate.h
  383. +++ b/content/browser/utility_sandbox_delegate.h
  384. @@ -34,7 +34,9 @@ class CONTENT_EXPORT UtilitySandboxedProcessLauncherDelegate
  385. public:
  386. UtilitySandboxedProcessLauncherDelegate(sandbox::mojom::Sandbox sandbox_type,
  387. const base::EnvironmentMap& env,
  388. - const base::CommandLine& cmd_line);
  389. + const base::FilePath& cwd,
  390. + const base::CommandLine& cmd_line,
  391. + bool inherit_environment);
  392. ~UtilitySandboxedProcessLauncherDelegate() override;
  393. sandbox::mojom::Sandbox GetSandboxType() override;
  394. @@ -59,9 +61,14 @@ class CONTENT_EXPORT UtilitySandboxedProcessLauncherDelegate
  395. ZygoteCommunication* GetZygote() override;
  396. #endif // BUILDFLAG(USE_ZYGOTE)
  397. -#if BUILDFLAG(IS_POSIX)
  398. base::EnvironmentMap GetEnvironment() override;
  399. -#endif // BUILDFLAG(IS_POSIX)
  400. + bool ShouldInheritEnvironment() override;
  401. + base::FilePath GetCurrentDirectory() override;
  402. +
  403. +#if BUILDFLAG(IS_WIN)
  404. + void SetFeedbackCursorOff(bool feedback_cursor_off);
  405. + bool ShouldShowFeedbackCursor() override;
  406. +#endif // BUILDFLAG(IS_WIN)
  407. #if BUILDFLAG(USE_ZYGOTE)
  408. void SetZygote(ZygoteCommunication* handle);
  409. @@ -72,9 +79,7 @@ class CONTENT_EXPORT UtilitySandboxedProcessLauncherDelegate
  410. #endif // BUILDFLAG(IS_MAC)
  411. private:
  412. -#if BUILDFLAG(IS_POSIX)
  413. base::EnvironmentMap env_;
  414. -#endif // BUILDFLAG(IS_POSIX)
  415. #if BUILDFLAG(IS_WIN)
  416. std::vector<base::FilePath> preload_libraries_;
  417. @@ -84,12 +89,17 @@ class CONTENT_EXPORT UtilitySandboxedProcessLauncherDelegate
  418. std::optional<raw_ptr<ZygoteCommunication>> zygote_;
  419. #endif // BUILDFLAG(USE_ZYGOTE)
  420. + base::FilePath current_directory_;
  421. const sandbox::mojom::Sandbox sandbox_type_;
  422. #if BUILDFLAG(IS_WIN)
  423. // If true then App Container will not be used for this utility process.
  424. const bool app_container_disabled_;
  425. #endif // BUILDFLAG(IS_WIN)
  426. base::CommandLine cmd_line_;
  427. + bool inherit_environment_;
  428. +#if BUILDFLAG(IS_WIN)
  429. + bool feedback_cursor_off_ = false;
  430. +#endif // BUILDFLAG(IS_WIN)
  431. };
  432. } // namespace content
  433. diff --git a/content/common/sandbox_init_win.cc b/content/common/sandbox_init_win.cc
  434. index 38733269e53b9874305942809373004f305ffdec..9f4f5f7dd7f2704e363f43c31ac930aeaabc2b45 100644
  435. --- a/content/common/sandbox_init_win.cc
  436. +++ b/content/common/sandbox_init_win.cc
  437. @@ -23,7 +23,7 @@ namespace content {
  438. sandbox::ResultCode StartSandboxedProcess(
  439. SandboxedProcessLauncherDelegate* delegate,
  440. const base::CommandLine& target_command_line,
  441. - const base::HandlesToInheritVector& handles_to_inherit,
  442. + const base::LaunchOptions* options,
  443. sandbox::StartSandboxedProcessCallback result_callback) {
  444. std::string type_str =
  445. target_command_line.GetSwitchValueASCII(switches::kProcessType);
  446. @@ -45,7 +45,7 @@ sandbox::ResultCode StartSandboxedProcess(
  447. }
  448. return sandbox::policy::SandboxWin::StartSandboxedProcess(
  449. - full_command_line, handles_to_inherit, delegate,
  450. + full_command_line, options, delegate,
  451. std::move(result_callback));
  452. }
  453. diff --git a/content/public/browser/service_process_host.cc b/content/public/browser/service_process_host.cc
  454. index 518d1413705f94bc03eadc4331a6b0f13825265f..3fa4c69377e253e0ed8262b7e77f8fb5c154d274 100644
  455. --- a/content/public/browser/service_process_host.cc
  456. +++ b/content/public/browser/service_process_host.cc
  457. @@ -52,12 +52,53 @@ ServiceProcessHost::Options::WithExtraCommandLineSwitches(
  458. return *this;
  459. }
  460. +#if BUILDFLAG(IS_WIN)
  461. +ServiceProcessHost::Options& ServiceProcessHost::Options::WithStdoutHandle(
  462. + base::win::ScopedHandle handle) {
  463. + stdout_handle = std::move(handle);
  464. + return *this;
  465. +}
  466. +
  467. +ServiceProcessHost::Options& ServiceProcessHost::Options::WithStderrHandle(
  468. + base::win::ScopedHandle handle) {
  469. + stderr_handle = std::move(handle);
  470. + return *this;
  471. +}
  472. +#elif BUILDFLAG(IS_POSIX)
  473. +ServiceProcessHost::Options& ServiceProcessHost::Options::WithAdditionalFds(
  474. + base::FileHandleMappingVector mapping) {
  475. + fds_to_remap = std::move(mapping);
  476. + return *this;
  477. +}
  478. +#endif
  479. +
  480. ServiceProcessHost::Options& ServiceProcessHost::Options::WithProcessCallback(
  481. base::OnceCallback<void(const base::Process&)> callback) {
  482. process_callback = std::move(callback);
  483. return *this;
  484. }
  485. +ServiceProcessHost::Options& ServiceProcessHost::Options::WithCurrentDirectory(
  486. + const base::FilePath& cwd) {
  487. + current_directory = cwd;
  488. + return *this;
  489. +}
  490. +
  491. +ServiceProcessHost::Options& ServiceProcessHost::Options::WithEnvironment(
  492. + const base::EnvironmentMap& env, bool new_environment) {
  493. + environment = env;
  494. + clear_environment = new_environment;
  495. + return *this;
  496. +}
  497. +
  498. +#if BUILDFLAG(IS_WIN)
  499. +ServiceProcessHost::Options& ServiceProcessHost::Options::WithFeedbackCursorOff(
  500. + bool turn_feedback_cursor_off) {
  501. + feedback_cursor_off = turn_feedback_cursor_off;
  502. + return *this;
  503. +}
  504. +#endif // #if BUILDFLAG(IS_WIN)
  505. +
  506. #if BUILDFLAG(IS_WIN)
  507. ServiceProcessHost::Options&
  508. ServiceProcessHost::Options::WithPreloadedLibraries(
  509. diff --git a/content/public/browser/service_process_host.h b/content/public/browser/service_process_host.h
  510. index 0062d2cb6634b8b29977a0312516b1b13936b40a..611a52e908f4cb70fbe5628e220a082e45320b70 100644
  511. --- a/content/public/browser/service_process_host.h
  512. +++ b/content/public/browser/service_process_host.h
  513. @@ -14,6 +14,7 @@
  514. #include "base/command_line.h"
  515. #include "base/functional/callback.h"
  516. #include "base/observer_list_types.h"
  517. +#include "base/process/launch.h"
  518. #include "base/process/process_handle.h"
  519. #include "content/common/content_export.h"
  520. #include "content/public/browser/service_process_info.h"
  521. @@ -28,6 +29,10 @@
  522. #include "base/types/pass_key.h"
  523. #endif // BUILDFLAG(IS_WIN)
  524. +#if BUILDFLAG(IS_WIN)
  525. +#include "base/win/scoped_handle.h"
  526. +#endif
  527. +
  528. namespace base {
  529. class Process;
  530. } // namespace base
  531. @@ -94,11 +99,35 @@ class CONTENT_EXPORT ServiceProcessHost {
  532. // Specifies extra command line switches to append before launch.
  533. Options& WithExtraCommandLineSwitches(std::vector<std::string> switches);
  534. +#if BUILDFLAG(IS_WIN)
  535. + // Specifies the handles for redirection of stdout and stderr.
  536. + Options& WithStdoutHandle(base::win::ScopedHandle stdout_handle);
  537. + Options& WithStderrHandle(base::win::ScopedHandle stderr_handle);
  538. +#elif BUILDFLAG(IS_POSIX)
  539. + // Specifies file descriptors to propagate into the child process
  540. + // based on the mapping.
  541. + Options& WithAdditionalFds(base::FileHandleMappingVector mapping);
  542. +#endif
  543. +
  544. // Specifies a callback to be invoked with service process once it's
  545. // launched. Will be on UI thread.
  546. Options& WithProcessCallback(
  547. base::OnceCallback<void(const base::Process&)>);
  548. + // Specifies the working directory for the launched process.
  549. + Options& WithCurrentDirectory(const base::FilePath& cwd);
  550. +
  551. + // Specifies the environment that should be applied to the process.
  552. + // |new_environment| controls whether the process should inherit
  553. + // environment from the parent process.
  554. + Options& WithEnvironment(const base::EnvironmentMap& environment,
  555. + bool new_environment);
  556. +
  557. +#if BUILDFLAG(IS_WIN)
  558. + // Specifies if the process should trigger mouse cursor feedback.
  559. + Options& WithFeedbackCursorOff(bool feedback_cursor_off);
  560. +#endif // #if BUILDFLAG(IS_WIN)
  561. +
  562. #if BUILDFLAG(IS_WIN)
  563. // Specifies libraries to preload before the sandbox is locked down. Paths
  564. // should be absolute paths. Libraries will be preloaded before sandbox
  565. @@ -127,11 +156,23 @@ class CONTENT_EXPORT ServiceProcessHost {
  566. std::optional<GURL> site;
  567. std::optional<int> child_flags;
  568. std::vector<std::string> extra_switches;
  569. +#if BUILDFLAG(IS_WIN)
  570. + base::win::ScopedHandle stdout_handle;
  571. + base::win::ScopedHandle stderr_handle;
  572. +#elif BUILDFLAG(IS_POSIX)
  573. + base::FileHandleMappingVector fds_to_remap;
  574. +#endif
  575. base::OnceCallback<void(const base::Process&)> process_callback;
  576. #if BUILDFLAG(IS_WIN)
  577. std::vector<base::FilePath> preload_libraries;
  578. #endif // BUILDFLAG(IS_WIN)
  579. std::optional<bool> allow_gpu_client;
  580. + base::FilePath current_directory;
  581. + base::EnvironmentMap environment;
  582. + bool clear_environment = false;
  583. +#if BUILDFLAG(IS_WIN)
  584. + bool feedback_cursor_off = false;
  585. +#endif // BUILDFLAG(IS_WIN)
  586. };
  587. // An interface which can be implemented and registered/unregistered with
  588. diff --git a/content/public/common/sandbox_init_win.h b/content/public/common/sandbox_init_win.h
  589. index 5c24090e3311a89dc2a9162045feaacda574bb99..b772a2a054e9d19025ebd2909acf1b920d389a95 100644
  590. --- a/content/public/common/sandbox_init_win.h
  591. +++ b/content/public/common/sandbox_init_win.h
  592. @@ -29,7 +29,7 @@ class SandboxedProcessLauncherDelegate;
  593. CONTENT_EXPORT sandbox::ResultCode StartSandboxedProcess(
  594. SandboxedProcessLauncherDelegate* delegate,
  595. const base::CommandLine& target_command_line,
  596. - const base::HandlesToInheritVector& handles_to_inherit,
  597. + const base::LaunchOptions* options,
  598. sandbox::StartSandboxedProcessCallback result_callback);
  599. } // namespace content
  600. diff --git a/content/public/common/sandboxed_process_launcher_delegate.cc b/content/public/common/sandboxed_process_launcher_delegate.cc
  601. index 4792134063125aba1a6a21cf9ab4a91d8d9e9486..61b98eb66722ed8e6cb83d5e08cf0c618449d1e0 100644
  602. --- a/content/public/common/sandboxed_process_launcher_delegate.cc
  603. +++ b/content/public/common/sandboxed_process_launcher_delegate.cc
  604. @@ -70,11 +70,23 @@ ZygoteCommunication* SandboxedProcessLauncherDelegate::GetZygote() {
  605. }
  606. #endif // BUILDFLAG(USE_ZYGOTE)
  607. -#if BUILDFLAG(IS_POSIX)
  608. base::EnvironmentMap SandboxedProcessLauncherDelegate::GetEnvironment() {
  609. return base::EnvironmentMap();
  610. }
  611. -#endif // BUILDFLAG(IS_POSIX)
  612. +
  613. +bool SandboxedProcessLauncherDelegate::ShouldInheritEnvironment() {
  614. + return true;
  615. +}
  616. +
  617. +base::FilePath SandboxedProcessLauncherDelegate::GetCurrentDirectory() {
  618. + return base::FilePath();
  619. +}
  620. +
  621. +#if BUILDFLAG(IS_WIN)
  622. +bool SandboxedProcessLauncherDelegate::ShouldShowFeedbackCursor() {
  623. + return true;
  624. +}
  625. +#endif // #if BUILDFLAG(IS_WIN)
  626. #if BUILDFLAG(IS_MAC)
  627. diff --git a/content/public/common/sandboxed_process_launcher_delegate.h b/content/public/common/sandboxed_process_launcher_delegate.h
  628. index b67f4f87d588386409a90cd49e8338272c6e0d51..c34a80ec8db1b868a7f387ea4a11d71d550cdb15 100644
  629. --- a/content/public/common/sandboxed_process_launcher_delegate.h
  630. +++ b/content/public/common/sandboxed_process_launcher_delegate.h
  631. @@ -8,6 +8,7 @@
  632. #include <optional>
  633. #include "base/environment.h"
  634. +#include "base/files/file_path.h"
  635. #include "base/files/scoped_file.h"
  636. #include "base/process/process.h"
  637. #include "build/build_config.h"
  638. @@ -62,10 +63,19 @@ class CONTENT_EXPORT SandboxedProcessLauncherDelegate
  639. virtual ZygoteCommunication* GetZygote();
  640. #endif // BUILDFLAG(USE_ZYGOTE)
  641. -#if BUILDFLAG(IS_POSIX)
  642. // Override this if the process needs a non-empty environment map.
  643. virtual base::EnvironmentMap GetEnvironment();
  644. -#endif // BUILDFLAG(IS_POSIX)
  645. +
  646. + // Override this if the process should not inherit parent environment.
  647. + virtual bool ShouldInheritEnvironment();
  648. +
  649. + // Specifies the directory to change to before executing the process.
  650. + virtual base::FilePath GetCurrentDirectory();
  651. +
  652. +#if BUILDFLAG(IS_WIN)
  653. + // Override this if the process should not trigger mouse cursor feedback.
  654. + virtual bool ShouldShowFeedbackCursor();
  655. +#endif // #if BUILDFLAG(IS_WIN)
  656. #if BUILDFLAG(IS_MAC)
  657. // Whether or not to disclaim TCC responsibility for the process, defaults to
  658. diff --git a/sandbox/policy/win/sandbox_win.cc b/sandbox/policy/win/sandbox_win.cc
  659. index 5f5857379ad34ccd1fb46564859bcef2d2a25d5e..6a39285e344d90b73199e73e48afaddbec3de628 100644
  660. --- a/sandbox/policy/win/sandbox_win.cc
  661. +++ b/sandbox/policy/win/sandbox_win.cc
  662. @@ -619,11 +619,9 @@ base::win::ScopedHandle CreateUnsandboxedJob() {
  663. // command line flag.
  664. ResultCode LaunchWithoutSandbox(
  665. const base::CommandLine& cmd_line,
  666. - const base::HandlesToInheritVector& handles_to_inherit,
  667. + base::LaunchOptions options,
  668. SandboxDelegate* delegate,
  669. base::Process* process) {
  670. - base::LaunchOptions options;
  671. - options.handles_to_inherit = handles_to_inherit;
  672. // Network process runs in a job even when unsandboxed. This is to ensure it
  673. // does not outlive the browser, which could happen if there is a lot of I/O
  674. // on process shutdown, in which case TerminateProcess can fail. See
  675. @@ -920,7 +918,7 @@ bool SandboxWin::InitTargetServices(TargetServices* target_services) {
  676. // static
  677. ResultCode SandboxWin::GeneratePolicyForSandboxedProcess(
  678. const base::CommandLine& cmd_line,
  679. - const base::HandlesToInheritVector& handles_to_inherit,
  680. + const base::LaunchOptions* options,
  681. SandboxDelegate* delegate,
  682. TargetPolicy* policy) {
  683. const base::CommandLine& launcher_process_command_line =
  684. @@ -934,7 +932,7 @@ ResultCode SandboxWin::GeneratePolicyForSandboxedProcess(
  685. }
  686. // Add any handles to be inherited to the policy.
  687. - for (HANDLE handle : handles_to_inherit)
  688. + for (HANDLE handle : options->handles_to_inherit)
  689. policy->AddHandleToShare(handle);
  690. if (!policy->GetConfig()->IsConfigured()) {
  691. @@ -949,6 +947,13 @@ ResultCode SandboxWin::GeneratePolicyForSandboxedProcess(
  692. // have no effect. These calls can fail with SBOX_ERROR_BAD_PARAMS.
  693. policy->SetStdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE));
  694. policy->SetStderrHandle(GetStdHandle(STD_ERROR_HANDLE));
  695. +#else
  696. + if (options->stdout_handle != nullptr && options->stdout_handle != INVALID_HANDLE_VALUE) {
  697. + policy->SetStdoutHandle(options->stdout_handle);
  698. + }
  699. + if (options->stderr_handle != nullptr && options->stderr_handle != INVALID_HANDLE_VALUE) {
  700. + policy->SetStderrHandle(options->stderr_handle);
  701. + }
  702. #endif
  703. if (!delegate->PreSpawnTarget(policy))
  704. @@ -960,7 +965,7 @@ ResultCode SandboxWin::GeneratePolicyForSandboxedProcess(
  705. // static
  706. ResultCode SandboxWin::StartSandboxedProcess(
  707. const base::CommandLine& cmd_line,
  708. - const base::HandlesToInheritVector& handles_to_inherit,
  709. + const base::LaunchOptions* options,
  710. SandboxDelegate* delegate,
  711. StartSandboxedProcessCallback result_callback) {
  712. SandboxLaunchTimer timer;
  713. @@ -970,7 +975,7 @@ ResultCode SandboxWin::StartSandboxedProcess(
  714. *base::CommandLine::ForCurrentProcess())) {
  715. base::Process process;
  716. ResultCode result =
  717. - LaunchWithoutSandbox(cmd_line, handles_to_inherit, delegate, &process);
  718. + LaunchWithoutSandbox(cmd_line, *options, delegate, &process);
  719. DWORD last_error = GetLastError();
  720. std::move(result_callback).Run(std::move(process), last_error, result);
  721. return SBOX_ALL_OK;
  722. @@ -980,7 +985,7 @@ ResultCode SandboxWin::StartSandboxedProcess(
  723. timer.OnPolicyCreated();
  724. ResultCode result = GeneratePolicyForSandboxedProcess(
  725. - cmd_line, handles_to_inherit, delegate, policy.get());
  726. + cmd_line, options, delegate, policy.get());
  727. if (SBOX_ALL_OK != result) {
  728. DWORD last_error = GetLastError();
  729. std::move(result_callback).Run(base::Process(), last_error, result);
  730. diff --git a/sandbox/policy/win/sandbox_win.h b/sandbox/policy/win/sandbox_win.h
  731. index 8fb74a2eefba49f95e4947ef9fd081ab8decebd4..3eed3d348132d5992c27bd8082a267fb42d4e431 100644
  732. --- a/sandbox/policy/win/sandbox_win.h
  733. +++ b/sandbox/policy/win/sandbox_win.h
  734. @@ -92,7 +92,7 @@ class SANDBOX_POLICY_EXPORT SandboxWin {
  735. // any other error.
  736. static ResultCode StartSandboxedProcess(
  737. const base::CommandLine& cmd_line,
  738. - const base::HandlesToInheritVector& handles_to_inherit,
  739. + const base::LaunchOptions* options,
  740. SandboxDelegate* delegate,
  741. StartSandboxedProcessCallback result_callback);
  742. @@ -105,7 +105,7 @@ class SANDBOX_POLICY_EXPORT SandboxWin {
  743. // of sandbox::ResultCode for any other error while constructing the policy.
  744. static ResultCode GeneratePolicyForSandboxedProcess(
  745. const base::CommandLine& cmd_line,
  746. - const base::HandlesToInheritVector& handles_to_inherit,
  747. + const base::LaunchOptions* options,
  748. SandboxDelegate* delegate,
  749. TargetPolicy* policy);