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 bbea8fff37040029996d1e91e592f6cb5bf8fbc2..13bbd8486279bf575010ab5ad62ba24a0d4cb24f 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 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 2fc9fabe67dc4d8c209247e46b57d27ec1a0fb90..ce73ed7f7070ee276511da674599364a468a2c8f 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. @@ -440,9 +466,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 6285d8eb5d05f7afbe45a314f423786d5ae01f53..5954f509ee80460ab73042ed39e236067e6f0d9b 100644
  325. --- a/content/browser/utility_sandbox_delegate.cc
  326. +++ b/content/browser/utility_sandbox_delegate.cc
  327. @@ -34,17 +34,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. @@ -113,11 +115,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 27cef06ded34680c6bfa3e954924de645a1b8217..7c114956a77da7b60526dd93593d84627356bb16 100644
  382. --- a/content/browser/utility_sandbox_delegate.h
  383. +++ b/content/browser/utility_sandbox_delegate.h
  384. @@ -30,7 +30,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. @@ -55,18 +57,21 @@ 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. #endif // BUILDFLAG(USE_ZYGOTE_HANDLE)
  410. private:
  411. -#if BUILDFLAG(IS_POSIX)
  412. base::EnvironmentMap env_;
  413. -#endif // BUILDFLAG(IS_POSIX)
  414. #if BUILDFLAG(IS_WIN)
  415. std::vector<base::FilePath> preload_libraries_;
  416. @@ -76,12 +81,17 @@ class CONTENT_EXPORT UtilitySandboxedProcessLauncherDelegate
  417. std::optional<raw_ptr<ZygoteCommunication>> zygote_;
  418. #endif // BUILDFLAG(USE_ZYGOTE)
  419. + base::FilePath current_directory_;
  420. const sandbox::mojom::Sandbox sandbox_type_;
  421. #if BUILDFLAG(IS_WIN)
  422. // If true then App Container will not be used for this utility process.
  423. const bool app_container_disabled_;
  424. #endif // BUILDFLAG(IS_WIN)
  425. base::CommandLine cmd_line_;
  426. + bool inherit_environment_;
  427. +#if BUILDFLAG(IS_WIN)
  428. + bool feedback_cursor_off_ = false;
  429. +#endif // BUILDFLAG(IS_WIN)
  430. };
  431. } // namespace content
  432. diff --git a/content/common/sandbox_init_win.cc b/content/common/sandbox_init_win.cc
  433. index 38733269e53b9874305942809373004f305ffdec..9f4f5f7dd7f2704e363f43c31ac930aeaabc2b45 100644
  434. --- a/content/common/sandbox_init_win.cc
  435. +++ b/content/common/sandbox_init_win.cc
  436. @@ -23,7 +23,7 @@ namespace content {
  437. sandbox::ResultCode StartSandboxedProcess(
  438. SandboxedProcessLauncherDelegate* delegate,
  439. const base::CommandLine& target_command_line,
  440. - const base::HandlesToInheritVector& handles_to_inherit,
  441. + const base::LaunchOptions* options,
  442. sandbox::StartSandboxedProcessCallback result_callback) {
  443. std::string type_str =
  444. target_command_line.GetSwitchValueASCII(switches::kProcessType);
  445. @@ -45,7 +45,7 @@ sandbox::ResultCode StartSandboxedProcess(
  446. }
  447. return sandbox::policy::SandboxWin::StartSandboxedProcess(
  448. - full_command_line, handles_to_inherit, delegate,
  449. + full_command_line, options, delegate,
  450. std::move(result_callback));
  451. }
  452. diff --git a/content/public/browser/service_process_host.cc b/content/public/browser/service_process_host.cc
  453. index 518d1413705f94bc03eadc4331a6b0f13825265f..3fa4c69377e253e0ed8262b7e77f8fb5c154d274 100644
  454. --- a/content/public/browser/service_process_host.cc
  455. +++ b/content/public/browser/service_process_host.cc
  456. @@ -52,12 +52,53 @@ ServiceProcessHost::Options::WithExtraCommandLineSwitches(
  457. return *this;
  458. }
  459. +#if BUILDFLAG(IS_WIN)
  460. +ServiceProcessHost::Options& ServiceProcessHost::Options::WithStdoutHandle(
  461. + base::win::ScopedHandle handle) {
  462. + stdout_handle = std::move(handle);
  463. + return *this;
  464. +}
  465. +
  466. +ServiceProcessHost::Options& ServiceProcessHost::Options::WithStderrHandle(
  467. + base::win::ScopedHandle handle) {
  468. + stderr_handle = std::move(handle);
  469. + return *this;
  470. +}
  471. +#elif BUILDFLAG(IS_POSIX)
  472. +ServiceProcessHost::Options& ServiceProcessHost::Options::WithAdditionalFds(
  473. + base::FileHandleMappingVector mapping) {
  474. + fds_to_remap = std::move(mapping);
  475. + return *this;
  476. +}
  477. +#endif
  478. +
  479. ServiceProcessHost::Options& ServiceProcessHost::Options::WithProcessCallback(
  480. base::OnceCallback<void(const base::Process&)> callback) {
  481. process_callback = std::move(callback);
  482. return *this;
  483. }
  484. +ServiceProcessHost::Options& ServiceProcessHost::Options::WithCurrentDirectory(
  485. + const base::FilePath& cwd) {
  486. + current_directory = cwd;
  487. + return *this;
  488. +}
  489. +
  490. +ServiceProcessHost::Options& ServiceProcessHost::Options::WithEnvironment(
  491. + const base::EnvironmentMap& env, bool new_environment) {
  492. + environment = env;
  493. + clear_environment = new_environment;
  494. + return *this;
  495. +}
  496. +
  497. +#if BUILDFLAG(IS_WIN)
  498. +ServiceProcessHost::Options& ServiceProcessHost::Options::WithFeedbackCursorOff(
  499. + bool turn_feedback_cursor_off) {
  500. + feedback_cursor_off = turn_feedback_cursor_off;
  501. + return *this;
  502. +}
  503. +#endif // #if BUILDFLAG(IS_WIN)
  504. +
  505. #if BUILDFLAG(IS_WIN)
  506. ServiceProcessHost::Options&
  507. ServiceProcessHost::Options::WithPreloadedLibraries(
  508. diff --git a/content/public/browser/service_process_host.h b/content/public/browser/service_process_host.h
  509. index 0062d2cb6634b8b29977a0312516b1b13936b40a..611a52e908f4cb70fbe5628e220a082e45320b70 100644
  510. --- a/content/public/browser/service_process_host.h
  511. +++ b/content/public/browser/service_process_host.h
  512. @@ -14,6 +14,7 @@
  513. #include "base/command_line.h"
  514. #include "base/functional/callback.h"
  515. #include "base/observer_list_types.h"
  516. +#include "base/process/launch.h"
  517. #include "base/process/process_handle.h"
  518. #include "content/common/content_export.h"
  519. #include "content/public/browser/service_process_info.h"
  520. @@ -28,6 +29,10 @@
  521. #include "base/types/pass_key.h"
  522. #endif // BUILDFLAG(IS_WIN)
  523. +#if BUILDFLAG(IS_WIN)
  524. +#include "base/win/scoped_handle.h"
  525. +#endif
  526. +
  527. namespace base {
  528. class Process;
  529. } // namespace base
  530. @@ -94,11 +99,35 @@ class CONTENT_EXPORT ServiceProcessHost {
  531. // Specifies extra command line switches to append before launch.
  532. Options& WithExtraCommandLineSwitches(std::vector<std::string> switches);
  533. +#if BUILDFLAG(IS_WIN)
  534. + // Specifies the handles for redirection of stdout and stderr.
  535. + Options& WithStdoutHandle(base::win::ScopedHandle stdout_handle);
  536. + Options& WithStderrHandle(base::win::ScopedHandle stderr_handle);
  537. +#elif BUILDFLAG(IS_POSIX)
  538. + // Specifies file descriptors to propagate into the child process
  539. + // based on the mapping.
  540. + Options& WithAdditionalFds(base::FileHandleMappingVector mapping);
  541. +#endif
  542. +
  543. // Specifies a callback to be invoked with service process once it's
  544. // launched. Will be on UI thread.
  545. Options& WithProcessCallback(
  546. base::OnceCallback<void(const base::Process&)>);
  547. + // Specifies the working directory for the launched process.
  548. + Options& WithCurrentDirectory(const base::FilePath& cwd);
  549. +
  550. + // Specifies the environment that should be applied to the process.
  551. + // |new_environment| controls whether the process should inherit
  552. + // environment from the parent process.
  553. + Options& WithEnvironment(const base::EnvironmentMap& environment,
  554. + bool new_environment);
  555. +
  556. +#if BUILDFLAG(IS_WIN)
  557. + // Specifies if the process should trigger mouse cursor feedback.
  558. + Options& WithFeedbackCursorOff(bool feedback_cursor_off);
  559. +#endif // #if BUILDFLAG(IS_WIN)
  560. +
  561. #if BUILDFLAG(IS_WIN)
  562. // Specifies libraries to preload before the sandbox is locked down. Paths
  563. // should be absolute paths. Libraries will be preloaded before sandbox
  564. @@ -127,11 +156,23 @@ class CONTENT_EXPORT ServiceProcessHost {
  565. std::optional<GURL> site;
  566. std::optional<int> child_flags;
  567. std::vector<std::string> extra_switches;
  568. +#if BUILDFLAG(IS_WIN)
  569. + base::win::ScopedHandle stdout_handle;
  570. + base::win::ScopedHandle stderr_handle;
  571. +#elif BUILDFLAG(IS_POSIX)
  572. + base::FileHandleMappingVector fds_to_remap;
  573. +#endif
  574. base::OnceCallback<void(const base::Process&)> process_callback;
  575. #if BUILDFLAG(IS_WIN)
  576. std::vector<base::FilePath> preload_libraries;
  577. #endif // BUILDFLAG(IS_WIN)
  578. std::optional<bool> allow_gpu_client;
  579. + base::FilePath current_directory;
  580. + base::EnvironmentMap environment;
  581. + bool clear_environment = false;
  582. +#if BUILDFLAG(IS_WIN)
  583. + bool feedback_cursor_off = false;
  584. +#endif // BUILDFLAG(IS_WIN)
  585. };
  586. // An interface which can be implemented and registered/unregistered with
  587. diff --git a/content/public/common/sandbox_init_win.h b/content/public/common/sandbox_init_win.h
  588. index 5c24090e3311a89dc2a9162045feaacda574bb99..b772a2a054e9d19025ebd2909acf1b920d389a95 100644
  589. --- a/content/public/common/sandbox_init_win.h
  590. +++ b/content/public/common/sandbox_init_win.h
  591. @@ -29,7 +29,7 @@ class SandboxedProcessLauncherDelegate;
  592. CONTENT_EXPORT sandbox::ResultCode StartSandboxedProcess(
  593. SandboxedProcessLauncherDelegate* delegate,
  594. const base::CommandLine& target_command_line,
  595. - const base::HandlesToInheritVector& handles_to_inherit,
  596. + const base::LaunchOptions* options,
  597. sandbox::StartSandboxedProcessCallback result_callback);
  598. } // namespace content
  599. diff --git a/content/public/common/sandboxed_process_launcher_delegate.cc b/content/public/common/sandboxed_process_launcher_delegate.cc
  600. index 8656215a709012eef80532e7aac197818ac292df..74ad339d8f8fcc62628006171e0a7ad265143625 100644
  601. --- a/content/public/common/sandboxed_process_launcher_delegate.cc
  602. +++ b/content/public/common/sandboxed_process_launcher_delegate.cc
  603. @@ -64,11 +64,23 @@ ZygoteCommunication* SandboxedProcessLauncherDelegate::GetZygote() {
  604. }
  605. #endif // BUILDFLAG(USE_ZYGOTE)
  606. -#if BUILDFLAG(IS_POSIX)
  607. base::EnvironmentMap SandboxedProcessLauncherDelegate::GetEnvironment() {
  608. return base::EnvironmentMap();
  609. }
  610. -#endif // BUILDFLAG(IS_POSIX)
  611. +
  612. +bool SandboxedProcessLauncherDelegate::ShouldInheritEnvironment() {
  613. + return true;
  614. +}
  615. +
  616. +base::FilePath SandboxedProcessLauncherDelegate::GetCurrentDirectory() {
  617. + return base::FilePath();
  618. +}
  619. +
  620. +#if BUILDFLAG(IS_WIN)
  621. +bool SandboxedProcessLauncherDelegate::ShouldShowFeedbackCursor() {
  622. + return true;
  623. +}
  624. +#endif // #if BUILDFLAG(IS_WIN)
  625. #if BUILDFLAG(IS_MAC)
  626. diff --git a/content/public/common/sandboxed_process_launcher_delegate.h b/content/public/common/sandboxed_process_launcher_delegate.h
  627. index 4b2ea0e2680c552b853fcbe4f5e4765a908f8915..6e8af760d986911ed6030b24244e9b21eeba865c 100644
  628. --- a/content/public/common/sandboxed_process_launcher_delegate.h
  629. +++ b/content/public/common/sandboxed_process_launcher_delegate.h
  630. @@ -6,6 +6,7 @@
  631. #define CONTENT_PUBLIC_COMMON_SANDBOXED_PROCESS_LAUNCHER_DELEGATE_H_
  632. #include "base/environment.h"
  633. +#include "base/files/file_path.h"
  634. #include "base/files/scoped_file.h"
  635. #include "base/process/process.h"
  636. #include "build/build_config.h"
  637. @@ -56,10 +57,19 @@ class CONTENT_EXPORT SandboxedProcessLauncherDelegate
  638. virtual ZygoteCommunication* GetZygote();
  639. #endif // BUILDFLAG(USE_ZYGOTE)
  640. -#if BUILDFLAG(IS_POSIX)
  641. // Override this if the process needs a non-empty environment map.
  642. virtual base::EnvironmentMap GetEnvironment();
  643. -#endif // BUILDFLAG(IS_POSIX)
  644. +
  645. + // Override this if the process should not inherit parent environment.
  646. + virtual bool ShouldInheritEnvironment();
  647. +
  648. + // Specifies the directory to change to before executing the process.
  649. + virtual base::FilePath GetCurrentDirectory();
  650. +
  651. +#if BUILDFLAG(IS_WIN)
  652. + // Override this if the process should not trigger mouse cursor feedback.
  653. + virtual bool ShouldShowFeedbackCursor();
  654. +#endif // #if BUILDFLAG(IS_WIN)
  655. #if BUILDFLAG(IS_MAC)
  656. // Whether or not to disclaim TCC responsibility for the process, defaults to
  657. diff --git a/sandbox/policy/win/sandbox_win.cc b/sandbox/policy/win/sandbox_win.cc
  658. index b550651a8a98132104d38df083717e1cb58567e4..52b9eddefcc6a2240babcac824058cd853d3058f 100644
  659. --- a/sandbox/policy/win/sandbox_win.cc
  660. +++ b/sandbox/policy/win/sandbox_win.cc
  661. @@ -619,11 +619,9 @@ base::win::ScopedHandle CreateUnsandboxedJob() {
  662. // command line flag.
  663. ResultCode LaunchWithoutSandbox(
  664. const base::CommandLine& cmd_line,
  665. - const base::HandlesToInheritVector& handles_to_inherit,
  666. + base::LaunchOptions options,
  667. SandboxDelegate* delegate,
  668. base::Process* process) {
  669. - base::LaunchOptions options;
  670. - options.handles_to_inherit = handles_to_inherit;
  671. // Network process runs in a job even when unsandboxed. This is to ensure it
  672. // does not outlive the browser, which could happen if there is a lot of I/O
  673. // on process shutdown, in which case TerminateProcess can fail. See
  674. @@ -920,7 +918,7 @@ bool SandboxWin::InitTargetServices(TargetServices* target_services) {
  675. // static
  676. ResultCode SandboxWin::GeneratePolicyForSandboxedProcess(
  677. const base::CommandLine& cmd_line,
  678. - const base::HandlesToInheritVector& handles_to_inherit,
  679. + const base::LaunchOptions* options,
  680. SandboxDelegate* delegate,
  681. TargetPolicy* policy) {
  682. const base::CommandLine& launcher_process_command_line =
  683. @@ -934,7 +932,7 @@ ResultCode SandboxWin::GeneratePolicyForSandboxedProcess(
  684. }
  685. // Add any handles to be inherited to the policy.
  686. - for (HANDLE handle : handles_to_inherit)
  687. + for (HANDLE handle : options->handles_to_inherit)
  688. policy->AddHandleToShare(handle);
  689. if (!policy->GetConfig()->IsConfigured()) {
  690. @@ -949,6 +947,13 @@ ResultCode SandboxWin::GeneratePolicyForSandboxedProcess(
  691. // have no effect. These calls can fail with SBOX_ERROR_BAD_PARAMS.
  692. policy->SetStdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE));
  693. policy->SetStderrHandle(GetStdHandle(STD_ERROR_HANDLE));
  694. +#else
  695. + if (options->stdout_handle != nullptr && options->stdout_handle != INVALID_HANDLE_VALUE) {
  696. + policy->SetStdoutHandle(options->stdout_handle);
  697. + }
  698. + if (options->stderr_handle != nullptr && options->stderr_handle != INVALID_HANDLE_VALUE) {
  699. + policy->SetStderrHandle(options->stderr_handle);
  700. + }
  701. #endif
  702. if (!delegate->PreSpawnTarget(policy))
  703. @@ -960,7 +965,7 @@ ResultCode SandboxWin::GeneratePolicyForSandboxedProcess(
  704. // static
  705. ResultCode SandboxWin::StartSandboxedProcess(
  706. const base::CommandLine& cmd_line,
  707. - const base::HandlesToInheritVector& handles_to_inherit,
  708. + const base::LaunchOptions* options,
  709. SandboxDelegate* delegate,
  710. StartSandboxedProcessCallback result_callback) {
  711. SandboxLaunchTimer timer;
  712. @@ -970,7 +975,7 @@ ResultCode SandboxWin::StartSandboxedProcess(
  713. *base::CommandLine::ForCurrentProcess())) {
  714. base::Process process;
  715. ResultCode result =
  716. - LaunchWithoutSandbox(cmd_line, handles_to_inherit, delegate, &process);
  717. + LaunchWithoutSandbox(cmd_line, *options, delegate, &process);
  718. DWORD last_error = GetLastError();
  719. std::move(result_callback).Run(std::move(process), last_error, result);
  720. return SBOX_ALL_OK;
  721. @@ -980,7 +985,7 @@ ResultCode SandboxWin::StartSandboxedProcess(
  722. timer.OnPolicyCreated();
  723. ResultCode result = GeneratePolicyForSandboxedProcess(
  724. - cmd_line, handles_to_inherit, delegate, policy.get());
  725. + cmd_line, options, delegate, policy.get());
  726. if (SBOX_ALL_OK != result) {
  727. DWORD last_error = GetLastError();
  728. std::move(result_callback).Run(base::Process(), last_error, result);
  729. diff --git a/sandbox/policy/win/sandbox_win.h b/sandbox/policy/win/sandbox_win.h
  730. index ede8bb552b2602fb06a6317399eb910e24a54216..c86744af9de2c366951d659851aaa9cac74b96de 100644
  731. --- a/sandbox/policy/win/sandbox_win.h
  732. +++ b/sandbox/policy/win/sandbox_win.h
  733. @@ -92,7 +92,7 @@ class SANDBOX_POLICY_EXPORT SandboxWin {
  734. // any other error.
  735. static ResultCode StartSandboxedProcess(
  736. const base::CommandLine& cmd_line,
  737. - const base::HandlesToInheritVector& handles_to_inherit,
  738. + const base::LaunchOptions* options,
  739. SandboxDelegate* delegate,
  740. StartSandboxedProcessCallback result_callback);
  741. @@ -105,7 +105,7 @@ class SANDBOX_POLICY_EXPORT SandboxWin {
  742. // of sandbox::ResultCode for any other error while constructing the policy.
  743. static ResultCode GeneratePolicyForSandboxedProcess(
  744. const base::CommandLine& cmd_line,
  745. - const base::HandlesToInheritVector& handles_to_inherit,
  746. + const base::LaunchOptions* options,
  747. SandboxDelegate* delegate,
  748. TargetPolicy* policy);