Avi Drissman | e4622aa | 2022-09-08 20:36:06 | [diff] [blame] | 1 | // Copyright 2013 The Chromium Authors |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | // This file contains functions for launching subprocesses. |
| 6 | |
| 7 | #ifndef BASE_PROCESS_LAUNCH_H_ |
| 8 | #define BASE_PROCESS_LAUNCH_H_ |
| 9 | |
avi | beced7c | 2015-12-24 06:47:59 | [diff] [blame] | 10 | #include <stddef.h> |
| 11 | |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 12 | #include <string> |
| 13 | #include <utility> |
| 14 | #include <vector> |
| 15 | |
| 16 | #include "base/base_export.h" |
Jan Wilken Dörrie | 6bdce49 | 2019-11-05 11:36:50 | [diff] [blame] | 17 | #include "base/command_line.h" |
[email protected] | b345c48 | 2013-08-30 18:00:39 | [diff] [blame] | 18 | #include "base/environment.h" |
Lei Zhang | 1757508 | 2021-05-10 20:19:18 | [diff] [blame] | 19 | #include "base/files/file_path.h" |
Wez | 4e86105 | 2023-07-12 12:18:57 | [diff] [blame^] | 20 | #include "base/memory/raw_ptr.h" |
rvargas | 6293e5b | 2014-12-01 22:53:09 | [diff] [blame] | 21 | #include "base/process/process.h" |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 22 | #include "base/process/process_handle.h" |
Wez | 4e86105 | 2023-07-12 12:18:57 | [diff] [blame^] | 23 | #include "base/strings/string_piece.h" |
Gabriel Charette | 6836c0d5 | 2021-01-11 17:40:26 | [diff] [blame] | 24 | #include "base/threading/thread_restrictions.h" |
Dave Tapuska | 6cd5272 | 2023-03-06 20:25:29 | [diff] [blame] | 25 | #include "build/blink_buildflags.h" |
avi | beced7c | 2015-12-24 06:47:59 | [diff] [blame] | 26 | #include "build/build_config.h" |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 27 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 28 | #if BUILDFLAG(IS_WIN) |
Bruce Dawson | 9df510e | 2021-07-14 15:23:08 | [diff] [blame] | 29 | #include "base/win/windows_types.h" |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 30 | #elif BUILDFLAG(IS_FUCHSIA) |
Wez | 5c3c6f15 | 2018-06-09 18:24:02 | [diff] [blame] | 31 | #include <lib/fdio/spawn.h> |
Scott Graham | fe0e9f46 | 2017-09-18 21:25:04 | [diff] [blame] | 32 | #include <zircon/types.h> |
scottmg | e5a1d49 | 2017-05-24 23:41:43 | [diff] [blame] | 33 | #endif |
| 34 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 35 | #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) |
Fabrice de Gans-Riberi | 306871de | 2018-05-16 19:38:39 | [diff] [blame] | 36 | #include "base/posix/file_descriptor_shuffle.h" |
| 37 | #endif |
| 38 | |
[email protected] | 285bc48 | 2023-03-02 22:35:36 | [diff] [blame] | 39 | namespace base { |
| 40 | |
Dave Tapuska | 6cd5272 | 2023-03-06 20:25:29 | [diff] [blame] | 41 | #if BUILDFLAG(IS_APPLE) |
| 42 | class MachRendezvousPort; |
| 43 | using MachPortsForRendezvous = std::map<uint32_t, MachRendezvousPort>; |
| 44 | #endif |
| 45 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 46 | #if BUILDFLAG(IS_WIN) |
[email protected] | 991bd8a | 2013-12-12 18:45:45 | [diff] [blame] | 47 | typedef std::vector<HANDLE> HandlesToInheritVector; |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 48 | #elif BUILDFLAG(IS_FUCHSIA) |
Kevin Marshall | ad910ae2 | 2018-06-16 05:40:53 | [diff] [blame] | 49 | struct PathToTransfer { |
| 50 | base::FilePath path; |
| 51 | zx_handle_t handle; |
| 52 | }; |
Wez | 1603c32 | 2017-08-10 05:24:54 | [diff] [blame] | 53 | struct HandleToTransfer { |
| 54 | uint32_t id; |
Scott Graham | fe0e9f46 | 2017-09-18 21:25:04 | [diff] [blame] | 55 | zx_handle_t handle; |
Wez | 1603c32 | 2017-08-10 05:24:54 | [diff] [blame] | 56 | }; |
| 57 | typedef std::vector<HandleToTransfer> HandlesToTransferVector; |
brettw | 3c98c7d3 | 2017-07-25 01:44:20 | [diff] [blame] | 58 | typedef std::vector<std::pair<int, int>> FileHandleMappingVector; |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 59 | #elif BUILDFLAG(IS_POSIX) |
Fabrice de Gans-Riberi | 306871de | 2018-05-16 19:38:39 | [diff] [blame] | 60 | typedef std::vector<std::pair<int, int>> FileHandleMappingVector; |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 61 | #endif // BUILDFLAG(IS_WIN) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 62 | |
| 63 | // Options for launching a subprocess that are passed to LaunchProcess(). |
| 64 | // The default constructor constructs the object with default options. |
[email protected] | b345c48 | 2013-08-30 18:00:39 | [diff] [blame] | 65 | struct BASE_EXPORT LaunchOptions { |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 66 | #if (BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)) && !BUILDFLAG(IS_APPLE) |
rickyz | a0b860b | 2015-01-16 18:19:34 | [diff] [blame] | 67 | // Delegate to be run in between fork and exec in the subprocess (see |
| 68 | // pre_exec_delegate below) |
| 69 | class BASE_EXPORT PreExecDelegate { |
| 70 | public: |
Chris Watkins | 091d629 | 2017-12-13 04:25:58 | [diff] [blame] | 71 | PreExecDelegate() = default; |
Peter Boström | 7319bbd | 2021-09-15 22:59:38 | [diff] [blame] | 72 | |
| 73 | PreExecDelegate(const PreExecDelegate&) = delete; |
| 74 | PreExecDelegate& operator=(const PreExecDelegate&) = delete; |
| 75 | |
Chris Watkins | 091d629 | 2017-12-13 04:25:58 | [diff] [blame] | 76 | virtual ~PreExecDelegate() = default; |
rickyz | a0b860b | 2015-01-16 18:19:34 | [diff] [blame] | 77 | |
| 78 | // Since this is to be run between fork and exec, and fork may have happened |
| 79 | // while multiple threads were running, this function needs to be async |
| 80 | // safe. |
| 81 | virtual void RunAsyncSafe() = 0; |
rickyz | a0b860b | 2015-01-16 18:19:34 | [diff] [blame] | 82 | }; |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 83 | #endif // BUILDFLAG(IS_POSIX) |
rickyz | a0b860b | 2015-01-16 18:19:34 | [diff] [blame] | 84 | |
[email protected] | b345c48 | 2013-08-30 18:00:39 | [diff] [blame] | 85 | LaunchOptions(); |
vmpstr | 7c787706 | 2016-02-18 22:12:24 | [diff] [blame] | 86 | LaunchOptions(const LaunchOptions&); |
[email protected] | b345c48 | 2013-08-30 18:00:39 | [diff] [blame] | 87 | ~LaunchOptions(); |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 88 | |
| 89 | // If true, wait for the process to complete. |
gab | 21691da | 2016-08-02 20:19:58 | [diff] [blame] | 90 | bool wait = false; |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 91 | |
sergeyu | 78205516 | 2016-04-06 08:57:59 | [diff] [blame] | 92 | // If not empty, change to this directory before executing the new process. |
| 93 | base::FilePath current_directory; |
| 94 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 95 | #if BUILDFLAG(IS_WIN) |
gab | 21691da | 2016-08-02 20:19:58 | [diff] [blame] | 96 | bool start_hidden = false; |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 97 | |
Joe Mason | cae7d8a | 2022-03-25 00:10:02 | [diff] [blame] | 98 | // Process will be started using ShellExecuteEx instead of CreateProcess so |
| 99 | // that it is elevated. LaunchProcess with this flag will have different |
| 100 | // behaviour due to ShellExecuteEx. Some common operations like OpenProcess |
| 101 | // will fail. Currently the only other supported LaunchOptions are |
| 102 | // |start_hidden| and |wait|. |
Alex Gough | b245386 | 2022-01-11 19:29:28 | [diff] [blame] | 103 | bool elevated = false; |
| 104 | |
S. Ganesh | c18d593 | 2018-11-05 03:45:31 | [diff] [blame] | 105 | // Sets STARTF_FORCEOFFFEEDBACK so that the feedback cursor is forced off |
| 106 | // while the process is starting. |
| 107 | bool feedback_cursor_off = false; |
| 108 | |
brettw | 3c98c7d3 | 2017-07-25 01:44:20 | [diff] [blame] | 109 | // Windows can inherit handles when it launches child processes. |
| 110 | // See https://blogs.msdn.microsoft.com/oldnewthing/20111216-00/?p=8873 |
| 111 | // for a good overview of Windows handle inheritance. |
| 112 | // |
| 113 | // Implementation note: it might be nice to implement in terms of |
Anton Bikineev | 7dd58ad | 2021-05-18 01:01:39 | [diff] [blame] | 114 | // absl::optional<>, but then the natural default state (vector not present) |
brettw | 3c98c7d3 | 2017-07-25 01:44:20 | [diff] [blame] | 115 | // would be "all inheritable handles" while we want "no inheritance." |
| 116 | enum class Inherit { |
| 117 | // Only those handles in |handles_to_inherit| vector are inherited. If the |
| 118 | // vector is empty, no handles are inherited. The handles in the vector must |
| 119 | // all be inheritable. |
| 120 | kSpecific, |
[email protected] | 991bd8a | 2013-12-12 18:45:45 | [diff] [blame] | 121 | |
brettw | 3c98c7d3 | 2017-07-25 01:44:20 | [diff] [blame] | 122 | // All handles in the current process which are inheritable are inherited. |
| 123 | // In production code this flag should be used only when running |
| 124 | // short-lived, trusted binaries, because open handles from other libraries |
| 125 | // and subsystems will leak to the child process, causing errors such as |
| 126 | // open socket hangs. There are also race conditions that can cause handle |
| 127 | // over-sharing. |
| 128 | // |
| 129 | // |handles_to_inherit| must be null. |
| 130 | // |
| 131 | // DEPRECATED. THIS SHOULD NOT BE USED. Explicitly map all handles that |
| 132 | // need to be shared in new code. |
| 133 | // TODO(brettw) bug 748258: remove this. |
| 134 | kAll |
| 135 | }; |
| 136 | Inherit inherit_mode = Inherit::kSpecific; |
| 137 | HandlesToInheritVector handles_to_inherit; |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 138 | |
[email protected] | 991bd8a | 2013-12-12 18:45:45 | [diff] [blame] | 139 | // If non-null, runs as if the user represented by the token had launched it. |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 140 | // Whether the application is visible on the interactive desktop depends on |
| 141 | // the token belonging to an interactive logon session. |
| 142 | // |
| 143 | // To avoid hard to diagnose problems, when specified this loads the |
| 144 | // environment variables associated with the user and if this operation fails |
| 145 | // the entire call fails as well. |
gab | 21691da | 2016-08-02 20:19:58 | [diff] [blame] | 146 | UserTokenHandle as_user = nullptr; |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 147 | |
| 148 | // If true, use an empty string for the desktop name. |
gab | 21691da | 2016-08-02 20:19:58 | [diff] [blame] | 149 | bool empty_desktop_name = false; |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 150 | |
[email protected] | 991bd8a | 2013-12-12 18:45:45 | [diff] [blame] | 151 | // If non-null, launches the application in that job object. The process will |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 152 | // be terminated immediately and LaunchProcess() will fail if assignment to |
| 153 | // the job object fails. |
gab | 21691da | 2016-08-02 20:19:58 | [diff] [blame] | 154 | HANDLE job_handle = nullptr; |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 155 | |
brettw | 3c98c7d3 | 2017-07-25 01:44:20 | [diff] [blame] | 156 | // Handles for the redirection of stdin, stdout and stderr. The caller should |
| 157 | // either set all three of them or none (i.e. there is no way to redirect |
| 158 | // stderr without redirecting stdin). |
| 159 | // |
| 160 | // The handles must be inheritable. Pseudo handles are used when stdout and |
| 161 | // stderr redirect to the console. In that case, GetFileType() will return |
| 162 | // FILE_TYPE_CHAR and they're automatically inherited by child processes. See |
| 163 | // https://msdn.microsoft.com/en-us/library/windows/desktop/ms682075.aspx |
| 164 | // Otherwise, the caller must ensure that the |inherit_mode| and/or |
| 165 | // |handles_to_inherit| set so that the handles are inherited. |
gab | 21691da | 2016-08-02 20:19:58 | [diff] [blame] | 166 | HANDLE stdin_handle = nullptr; |
| 167 | HANDLE stdout_handle = nullptr; |
| 168 | HANDLE stderr_handle = nullptr; |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 169 | |
| 170 | // If set to true, ensures that the child process is launched with the |
| 171 | // CREATE_BREAKAWAY_FROM_JOB flag which allows it to breakout of the parent |
| 172 | // job if any. |
gab | 21691da | 2016-08-02 20:19:58 | [diff] [blame] | 173 | bool force_breakaway_from_job_ = false; |
Greg Thompson | 47faf20 | 2018-05-18 20:59:03 | [diff] [blame] | 174 | |
| 175 | // If set to true, permission to bring windows to the foreground is passed to |
| 176 | // the launched process if the current process has such permission. |
| 177 | bool grant_foreground_privilege = false; |
Alex Gough | d383c77 | 2021-02-17 04:39:34 | [diff] [blame] | 178 | |
| 179 | // If set to true, sets a process mitigation flag to disable Hardware-enforced |
| 180 | // Stack Protection for the process. |
| 181 | // This overrides /cetcompat if set on the executable. See: |
| 182 | // https://docs.microsoft.com/en-us/cpp/build/reference/cetcompat?view=msvc-160 |
| 183 | // If not supported by Windows, has no effect. This flag weakens security by |
| 184 | // turning off ROP protection. |
| 185 | bool disable_cetcompat = false; |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 186 | #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) |
brettw | 3c98c7d3 | 2017-07-25 01:44:20 | [diff] [blame] | 187 | // Remap file descriptors according to the mapping of src_fd->dest_fd to |
| 188 | // propagate FDs into the child process. |
| 189 | FileHandleMappingVector fds_to_remap; |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 190 | #endif // BUILDFLAG(IS_WIN) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 191 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 192 | #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) |
David Benjamin | 76ee79eb | 2019-03-15 17:02:09 | [diff] [blame] | 193 | // Set/unset environment variables. These are applied on top of the parent |
| 194 | // process environment. Empty (the default) means to inherit the same |
| 195 | // environment. See internal::AlterEnvironment(). |
| 196 | EnvironmentMap environment; |
| 197 | |
| 198 | // Clear the environment for the new process before processing changes from |
| 199 | // |environment|. |
| 200 | bool clear_environment = false; |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 201 | #endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) |
David Benjamin | 76ee79eb | 2019-03-15 17:02:09 | [diff] [blame] | 202 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 203 | #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 204 | // If non-zero, start the process using clone(), using flags as provided. |
rickyz | f1eb9cc | 2015-01-13 22:59:48 | [diff] [blame] | 205 | // Unlike in clone, clone_flags may not contain a custom termination signal |
| 206 | // that is sent to the parent when the child dies. The termination signal will |
| 207 | // always be set to SIGCHLD. |
gab | 21691da | 2016-08-02 20:19:58 | [diff] [blame] | 208 | int clone_flags = 0; |
[email protected] | d078691 | 2014-04-09 20:06:26 | [diff] [blame] | 209 | |
| 210 | // By default, child processes will have the PR_SET_NO_NEW_PRIVS bit set. If |
| 211 | // true, then this bit will not be set in the new child process. |
gab | 21691da | 2016-08-02 20:19:58 | [diff] [blame] | 212 | bool allow_new_privs = false; |
phajdan.jr | ed5ed8f4 | 2015-03-13 21:40:13 | [diff] [blame] | 213 | |
| 214 | // Sets parent process death signal to SIGKILL. |
gab | 21691da | 2016-08-02 20:19:58 | [diff] [blame] | 215 | bool kill_on_parent_death = false; |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 216 | #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 217 | |
Dave Tapuska | 6cd5272 | 2023-03-06 20:25:29 | [diff] [blame] | 218 | #if BUILDFLAG(IS_MAC) || (BUILDFLAG(IS_IOS) && BUILDFLAG(USE_BLINK)) |
Robert Sesek | a6d5986 | 2019-03-05 16:06:47 | [diff] [blame] | 219 | // Mach ports that will be accessible to the child process. These are not |
| 220 | // directly inherited across process creation, but they are stored by a Mach |
| 221 | // IPC server that a child process can communicate with to retrieve them. |
| 222 | // |
| 223 | // After calling LaunchProcess(), any rights that were transferred with MOVE |
| 224 | // dispositions will be consumed, even on failure. |
| 225 | // |
| 226 | // See base/mac/mach_port_rendezvous.h for details. |
| 227 | MachPortsForRendezvous mach_ports_for_rendezvous; |
Robert Sesek | 34025cb9 | 2019-08-22 00:07:53 | [diff] [blame] | 228 | |
Dave Tapuska | ed322d0 | 2023-03-07 23:33:33 | [diff] [blame] | 229 | // Apply a process scheduler policy to enable mitigations against CPU side- |
| 230 | // channel attacks. |
| 231 | bool enable_cpu_security_mitigations = false; |
| 232 | #endif // BUILDFLAG(IS_MAC) || (BUILDFLAG(IS_IOS) && BUILDFLAG(USE_BLINK)) |
| 233 | |
| 234 | #if BUILDFLAG(IS_MAC) |
Robert Sesek | 34025cb9 | 2019-08-22 00:07:53 | [diff] [blame] | 235 | // When a child process is launched, the system tracks the parent process |
| 236 | // with a concept of "responsibility". The responsible process will be |
| 237 | // associated with any requests for private data stored on the system via |
| 238 | // the TCC subsystem. When launching processes that run foreign/third-party |
| 239 | // code, the responsibility for the child process should be disclaimed so |
| 240 | // that any TCC requests are not associated with the parent. |
| 241 | bool disclaim_responsibility = false; |
Dave Tapuska | 6cd5272 | 2023-03-06 20:25:29 | [diff] [blame] | 242 | #endif // BUILDFLAG(IS_MAC) || (BUILDFLAG(IS_IOS) && BUILDFLAG(USE_BLINK)) |
Robert Sesek | a6d5986 | 2019-03-05 16:06:47 | [diff] [blame] | 243 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 244 | #if BUILDFLAG(IS_FUCHSIA) |
scottmg | e5a1d49 | 2017-05-24 23:41:43 | [diff] [blame] | 245 | // If valid, launches the application in that job object. |
Scott Graham | fe0e9f46 | 2017-09-18 21:25:04 | [diff] [blame] | 246 | zx_handle_t job_handle = ZX_HANDLE_INVALID; |
Wez | 1603c32 | 2017-08-10 05:24:54 | [diff] [blame] | 247 | |
| 248 | // Specifies additional handles to transfer (not duplicate) to the child |
Wez | 0629d40 | 2018-06-06 00:26:43 | [diff] [blame] | 249 | // process. Each entry is an <id,handle> pair, with an |id| created using the |
Kevin Marshall | 40dc4360 | 2018-06-16 01:33:55 | [diff] [blame] | 250 | // PA_HND() macro. The child retrieves the handle |
| 251 | // |zx_take_startup_handle(id)|. The supplied handles are consumed by |
| 252 | // LaunchProcess() even on failure. |
Wez | 35e50b5 | 2018-12-01 01:52:44 | [diff] [blame] | 253 | // Note that PA_USER1 ids are reserved for use by AddHandleToTransfer(), below |
| 254 | // and by convention PA_USER0 is reserved for use by the embedding |
| 255 | // application. |
Wez | 1603c32 | 2017-08-10 05:24:54 | [diff] [blame] | 256 | HandlesToTransferVector handles_to_transfer; |
Kevin Marshall | 65c2670 | 2017-09-25 18:21:42 | [diff] [blame] | 257 | |
Wez | 35e50b5 | 2018-12-01 01:52:44 | [diff] [blame] | 258 | // Allocates a unique id for |handle| in |handles_to_transfer|, inserts it, |
| 259 | // and returns the generated id. |
| 260 | static uint32_t AddHandleToTransfer( |
| 261 | HandlesToTransferVector* handles_to_transfer, |
| 262 | zx_handle_t handle); |
| 263 | |
Wez | 0629d40 | 2018-06-06 00:26:43 | [diff] [blame] | 264 | // Specifies which basic capabilities to grant to the child process. |
| 265 | // By default the child process will receive the caller's complete namespace, |
Fabrice de Gans-Riberi | 930bbf4b | 2021-02-04 23:18:56 | [diff] [blame] | 266 | // access to the current base::GetDefaultJob(), handles for stdio and access |
| 267 | // to the dynamic library loader. |
Wez | 0629d40 | 2018-06-06 00:26:43 | [diff] [blame] | 268 | // Note that the child is always provided access to the loader service. |
| 269 | uint32_t spawn_flags = FDIO_SPAWN_CLONE_NAMESPACE | FDIO_SPAWN_CLONE_STDIO | |
| 270 | FDIO_SPAWN_CLONE_JOB; |
Kevin Marshall | 2bd0455 | 2018-02-01 21:23:45 | [diff] [blame] | 271 | |
Wez | 0629d40 | 2018-06-06 00:26:43 | [diff] [blame] | 272 | // Specifies paths to clone from the calling process' namespace into that of |
Kevin Marshall | ad910ae2 | 2018-06-16 05:40:53 | [diff] [blame] | 273 | // the child process. If |paths_to_clone| is empty then the process will |
| 274 | // receive either a full copy of the parent's namespace, or an empty one, |
| 275 | // depending on whether FDIO_SPAWN_CLONE_NAMESPACE is set. |
Wez | 821a3b8 | 2023-04-04 17:55:32 | [diff] [blame] | 276 | // Process launch will fail if `paths_to_clone` and `paths_to_transfer` |
| 277 | // together contain conflicting paths (e.g. overlaps or duplicates). |
Wez | 4e86105 | 2023-07-12 12:18:57 | [diff] [blame^] | 278 | std::vector<FilePath> paths_to_clone; |
Kevin Marshall | ad910ae2 | 2018-06-16 05:40:53 | [diff] [blame] | 279 | |
| 280 | // Specifies handles which will be installed as files or directories in the |
Wez | 821a3b8 | 2023-04-04 17:55:32 | [diff] [blame] | 281 | // child process' namespace. |
| 282 | // Process launch will fail if `paths_to_clone` and `paths_to_transfer` |
| 283 | // together contain conflicting paths (e.g. overlaps or duplicates). |
Kevin Marshall | ad910ae2 | 2018-06-16 05:40:53 | [diff] [blame] | 284 | std::vector<PathToTransfer> paths_to_transfer; |
Sergey Ulanov | 53ab7dd | 2019-08-27 17:53:18 | [diff] [blame] | 285 | |
| 286 | // Suffix that will be added to the process name. When specified process name |
| 287 | // will be set to "<binary_name><process_suffix>". |
| 288 | std::string process_name_suffix; |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 289 | #endif // BUILDFLAG(IS_FUCHSIA) |
scottmg | e5a1d49 | 2017-05-24 23:41:43 | [diff] [blame] | 290 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 291 | #if BUILDFLAG(IS_POSIX) |
rkjnsn | 732f03d | 2016-10-03 17:59:54 | [diff] [blame] | 292 | // If not empty, launch the specified executable instead of |
| 293 | // cmdline.GetProgram(). This is useful when it is necessary to pass a custom |
| 294 | // argv[0]. |
| 295 | base::FilePath real_path; |
| 296 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 297 | #if !BUILDFLAG(IS_APPLE) |
rickyz | a0b860b | 2015-01-16 18:19:34 | [diff] [blame] | 298 | // If non-null, a delegate to be run immediately prior to executing the new |
| 299 | // program in the child process. |
| 300 | // |
| 301 | // WARNING: If LaunchProcess is called in the presence of multiple threads, |
| 302 | // code running in this delegate essentially needs to be async-signal safe |
| 303 | // (see man 7 signal for a list of allowed functions). |
Keishi Hattori | 0e45c02 | 2021-11-27 09:25:52 | [diff] [blame] | 304 | raw_ptr<PreExecDelegate> pre_exec_delegate = nullptr; |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 305 | #endif // !BUILDFLAG(IS_APPLE) |
Wez | dc9eb2b12 | 2018-01-09 04:43:07 | [diff] [blame] | 306 | |
| 307 | // Each element is an RLIMIT_* constant that should be raised to its |
| 308 | // rlim_max. This pointer is owned by the caller and must live through |
| 309 | // the call to LaunchProcess(). |
Keishi Hattori | 0e45c02 | 2021-11-27 09:25:52 | [diff] [blame] | 310 | raw_ptr<const std::vector<int>> maximize_rlimits = nullptr; |
Wez | dc9eb2b12 | 2018-01-09 04:43:07 | [diff] [blame] | 311 | |
| 312 | // If true, start the process in a new process group, instead of |
| 313 | // inheriting the parent's process group. The pgid of the child process |
| 314 | // will be the same as its pid. |
| 315 | bool new_process_group = false; |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 316 | #endif // BUILDFLAG(IS_POSIX) |
rickyz | a0b860b | 2015-01-16 18:19:34 | [diff] [blame] | 317 | |
Eric Willigers | 611cf54 | 2022-04-28 02:22:14 | [diff] [blame] | 318 | #if BUILDFLAG(IS_CHROMEOS) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 319 | // If non-negative, the specified file descriptor will be set as the launched |
| 320 | // process' controlling terminal. |
gab | 21691da | 2016-08-02 20:19:58 | [diff] [blame] | 321 | int ctrl_terminal_fd = -1; |
Eric Willigers | 611cf54 | 2022-04-28 02:22:14 | [diff] [blame] | 322 | #endif // BUILDFLAG(IS_CHROMEOS) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 323 | }; |
| 324 | |
| 325 | // Launch a process via the command line |cmdline|. |
| 326 | // See the documentation of LaunchOptions for details on |options|. |
| 327 | // |
rvargas | c40cfc6 | 2014-12-02 02:46:36 | [diff] [blame] | 328 | // Returns a valid Process upon success. |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 329 | // |
| 330 | // Unix-specific notes: |
| 331 | // - All file descriptors open in the parent process will be closed in the |
| 332 | // child process except for any preserved by options::fds_to_remap, and |
| 333 | // stdin, stdout, and stderr. If not remapped by options::fds_to_remap, |
| 334 | // stdin is reopened as /dev/null, and the child is allowed to inherit its |
| 335 | // parent's stdout and stderr. |
| 336 | // - If the first argument on the command line does not contain a slash, |
| 337 | // PATH will be searched. (See man execvp.) |
rvargas | c40cfc6 | 2014-12-02 02:46:36 | [diff] [blame] | 338 | BASE_EXPORT Process LaunchProcess(const CommandLine& cmdline, |
| 339 | const LaunchOptions& options); |
| 340 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 341 | #if BUILDFLAG(IS_WIN) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 342 | // Windows-specific LaunchProcess that takes the command line as a |
| 343 | // string. Useful for situations where you need to control the |
| 344 | // command line arguments directly, but prefer the CommandLine version |
Joe Mason | cae7d8a | 2022-03-25 00:10:02 | [diff] [blame] | 345 | // if launching Chrome itself. Also prefer the CommandLine version if |
| 346 | // `options.elevated` is set because `cmdline` needs to be parsed for |
| 347 | // ShellExecuteEx. |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 348 | // |
| 349 | // The first command line argument should be the path to the process, |
| 350 | // and don't forget to quote it. |
| 351 | // |
| 352 | // Example (including literal quotes) |
| 353 | // cmdline = "c:\windows\explorer.exe" -foo "c:\bar\" |
Jan Wilken Dörrie | 6bdce49 | 2019-11-05 11:36:50 | [diff] [blame] | 354 | BASE_EXPORT Process LaunchProcess(const CommandLine::StringType& cmdline, |
rvargas | 6181277 | 2014-12-05 03:14:54 | [diff] [blame] | 355 | const LaunchOptions& options); |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 356 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 357 | #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 358 | // A POSIX-specific version of LaunchProcess that takes an argv array |
| 359 | // instead of a CommandLine. Useful for situations where you need to |
| 360 | // control the command line arguments directly, but prefer the |
| 361 | // CommandLine version if launching Chrome itself. |
rvargas | 02a9986 | 2015-01-10 00:46:12 | [diff] [blame] | 362 | BASE_EXPORT Process LaunchProcess(const std::vector<std::string>& argv, |
| 363 | const LaunchOptions& options); |
| 364 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 365 | #if !BUILDFLAG(IS_APPLE) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 366 | // Close all file descriptors, except those which are a destination in the |
| 367 | // given multimap. Only call this function in a child process where you know |
| 368 | // that there aren't any other threads. |
| 369 | BASE_EXPORT void CloseSuperfluousFds(const InjectiveMultimap& saved_map); |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 370 | #endif // BUILDFLAG(IS_APPLE) |
| 371 | #endif // BUILDFLAG(IS_WIN) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 372 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 373 | #if BUILDFLAG(IS_WIN) |
[email protected] | 15db082 | 2013-09-13 21:24:47 | [diff] [blame] | 374 | // Set |job_object|'s JOBOBJECT_EXTENDED_LIMIT_INFORMATION |
| 375 | // BasicLimitInformation.LimitFlags to |limit_flags|. |
| 376 | BASE_EXPORT bool SetJobObjectLimitFlags(HANDLE job_object, DWORD limit_flags); |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 377 | |
| 378 | // Output multi-process printf, cout, cerr, etc to the cmd.exe console that ran |
| 379 | // chrome. This is not thread-safe: only call from main thread. |
jam | 79dc59a | 2015-08-17 03:38:16 | [diff] [blame] | 380 | BASE_EXPORT void RouteStdioToConsole(bool create_console_if_not_found); |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 381 | #endif // BUILDFLAG(IS_WIN) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 382 | |
| 383 | // Executes the application specified by |cl| and wait for it to exit. Stores |
| 384 | // the output (stdout) in |output|. Redirects stderr to /dev/null. Returns true |
| 385 | // on success (application launched and exited cleanly, with exit code |
| 386 | // indicating success). |
| 387 | BASE_EXPORT bool GetAppOutput(const CommandLine& cl, std::string* output); |
| 388 | |
jam | 79dc59a | 2015-08-17 03:38:16 | [diff] [blame] | 389 | // Like GetAppOutput, but also includes stderr. |
| 390 | BASE_EXPORT bool GetAppOutputAndError(const CommandLine& cl, |
| 391 | std::string* output); |
| 392 | |
Zijie He | e9d42a3 | 2017-07-17 20:37:55 | [diff] [blame] | 393 | // A version of |GetAppOutput()| which also returns the exit code of the |
| 394 | // executed command. Returns true if the application runs and exits cleanly. If |
| 395 | // this is the case the exit code of the application is available in |
| 396 | // |*exit_code|. |
| 397 | BASE_EXPORT bool GetAppOutputWithExitCode(const CommandLine& cl, |
| 398 | std::string* output, int* exit_code); |
| 399 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 400 | #if BUILDFLAG(IS_WIN) |
[email protected] | 7eb6bec6 | 2013-12-05 22:41:04 | [diff] [blame] | 401 | // A Windows-specific version of GetAppOutput that takes a command line string |
| 402 | // instead of a CommandLine object. Useful for situations where you need to |
| 403 | // control the command line arguments directly. |
Jan Wilken Dörrie | 6bdce49 | 2019-11-05 11:36:50 | [diff] [blame] | 404 | BASE_EXPORT bool GetAppOutput(CommandLine::StringPieceType cl, |
| 405 | std::string* output); |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 406 | #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 407 | // A POSIX-specific version of GetAppOutput that takes an argv array |
| 408 | // instead of a CommandLine. Useful for situations where you need to |
| 409 | // control the command line arguments directly. |
| 410 | BASE_EXPORT bool GetAppOutput(const std::vector<std::string>& argv, |
| 411 | std::string* output); |
| 412 | |
jbudorick | 86c756c | 2017-03-29 17:33:54 | [diff] [blame] | 413 | // Like the above POSIX-specific version of GetAppOutput, but also includes |
| 414 | // stderr. |
| 415 | BASE_EXPORT bool GetAppOutputAndError(const std::vector<std::string>& argv, |
| 416 | std::string* output); |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 417 | #endif // BUILDFLAG(IS_WIN) |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 418 | |
| 419 | // If supported on the platform, and the user has sufficent rights, increase |
| 420 | // the current process's scheduling priority to a high priority. |
| 421 | BASE_EXPORT void RaiseProcessToHighPriority(); |
| 422 | |
[email protected] | d078691 | 2014-04-09 20:06:26 | [diff] [blame] | 423 | // Creates a LaunchOptions object suitable for launching processes in a test |
| 424 | // binary. This should not be called in production/released code. |
| 425 | BASE_EXPORT LaunchOptions LaunchOptionsForTest(); |
| 426 | |
Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 427 | #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) |
rickyz | a2f6d74 | 2015-01-21 21:57:34 | [diff] [blame] | 428 | // A wrapper for clone with fork-like behavior, meaning that it returns the |
| 429 | // child's pid in the parent and 0 in the child. |flags|, |ptid|, and |ctid| are |
| 430 | // as in the clone system call (the CLONE_VM flag is not supported). |
| 431 | // |
| 432 | // This function uses the libc clone wrapper (which updates libc's pid cache) |
| 433 | // internally, so callers may expect things like getpid() to work correctly |
Mostyn Bramley-Moore | d0ecd6a | 2017-12-06 19:13:21 | [diff] [blame] | 434 | // after in both the child and parent. |
rickyz | a2f6d74 | 2015-01-21 21:57:34 | [diff] [blame] | 435 | // |
| 436 | // As with fork(), callers should be extremely careful when calling this while |
| 437 | // multiple threads are running, since at the time the fork happened, the |
| 438 | // threads could have been in any state (potentially holding locks, etc.). |
| 439 | // Callers should most likely call execve() in the child soon after calling |
| 440 | // this. |
Tom Anderson | 24df4195 | 2017-07-25 02:41:01 | [diff] [blame] | 441 | // |
| 442 | // It is unsafe to use any pthread APIs after ForkWithFlags(). |
| 443 | // However, performing an exec() will lift this restriction. |
Peter Kasting | 25acd594 | 2022-07-07 17:45:15 | [diff] [blame] | 444 | BASE_EXPORT pid_t ForkWithFlags(int flags, pid_t* ptid, pid_t* ctid); |
rickyz | a2f6d74 | 2015-01-21 21:57:34 | [diff] [blame] | 445 | #endif |
| 446 | |
Gabriel Charette | 6836c0d5 | 2021-01-11 17:40:26 | [diff] [blame] | 447 | namespace internal { |
| 448 | |
| 449 | // Friend and derived class of ScopedAllowBaseSyncPrimitives which allows |
| 450 | // GetAppOutputInternal() to join a process. GetAppOutputInternal() can't itself |
| 451 | // be a friend of ScopedAllowBaseSyncPrimitives because it is in the anonymous |
| 452 | // namespace. |
Peter Kasting | 89a70ae3 | 2023-03-09 02:15:39 | [diff] [blame] | 453 | class [[maybe_unused, nodiscard]] GetAppOutputScopedAllowBaseSyncPrimitives |
| 454 | : public base::ScopedAllowBaseSyncPrimitives{}; |
Gabriel Charette | 6836c0d5 | 2021-01-11 17:40:26 | [diff] [blame] | 455 | |
| 456 | } // namespace internal |
| 457 | |
[email protected] | 300c386 | 2013-07-17 18:12:40 | [diff] [blame] | 458 | } // namespace base |
| 459 | |
| 460 | #endif // BASE_PROCESS_LAUNCH_H_ |