blob: 75cafbe0dbd7d4b3dca4c8fe56e17cd836123588 [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2017 The Chromium Authors
jcivelli828cd7f2017-01-18 19:50:462// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Gabriel Charettef3851332022-04-28 23:39:185#include "base/command_line.h"
jcivellidad0cef2017-02-16 18:38:596#include "base/path_service.h"
jcivelli828cd7f2017-01-18 19:50:467#include "base/posix/global_descriptors.h"
Alexander Alekseev0df843b2023-08-09 13:33:158#include "base/trace_event/trace_event.h"
Tom Sepezd1a315b2018-01-11 18:18:009#include "build/build_config.h"
jcivelli828cd7f2017-01-18 19:50:4610#include "content/browser/child_process_launcher.h"
11#include "content/browser/child_process_launcher_helper.h"
12#include "content/browser/child_process_launcher_helper_posix.h"
Vladimir Levin11a23b12017-09-11 23:13:3013#include "content/browser/sandbox_host_linux.h"
Robert Sesek8621aef02020-06-25 18:17:3714#include "content/browser/zygote_host/zygote_host_impl_linux.h"
15#include "content/common/zygote/zygote_communication_linux.h"
Xi Han89d93df2018-03-09 20:55:0716#include "content/public/browser/child_process_launcher_utils.h"
jcivelli828cd7f2017-01-18 19:50:4617#include "content/public/browser/content_browser_client.h"
jcivelli828cd7f2017-01-18 19:50:4618#include "content/public/common/content_client.h"
Kuo-Hsin Yangbff00c72020-02-14 05:59:2319#include "content/public/common/content_constants.h"
Shintaro Kawamuraf29c8fdf2024-03-28 03:40:0820#include "content/public/common/content_features.h"
jcivelli828cd7f2017-01-18 19:50:4621#include "content/public/common/content_switches.h"
22#include "content/public/common/result_codes.h"
23#include "content/public/common/sandboxed_process_launcher_delegate.h"
Robert Sesek8621aef02020-06-25 18:17:3724#include "content/public/common/zygote/sandbox_support_linux.h"
25#include "content/public/common/zygote/zygote_handle.h"
Robert Sesek7d0b49b2020-07-08 18:31:2726#include "sandbox/policy/linux/sandbox_linux.h"
jcivelli828cd7f2017-01-18 19:50:4627
28namespace content {
29namespace internal {
30
Arthur Sonzognic686e8f2024-01-11 08:36:3731std::optional<mojo::NamedPlatformChannel>
Will Harrisa7fb9d02023-02-15 02:08:2432ChildProcessLauncherHelper::CreateNamedPlatformChannelOnLauncherThread() {
33 DCHECK(CurrentlyOnProcessLauncherTaskRunner());
Arthur Sonzognic686e8f2024-01-11 08:36:3734 return std::nullopt;
jcivelli828cd7f2017-01-18 19:50:4635}
36
37void ChildProcessLauncherHelper::BeforeLaunchOnClientThread() {
Ken Rockot8e23c3ab2019-08-01 23:39:1038 DCHECK(client_task_runner_->RunsTasksInCurrentSequence());
jcivelli828cd7f2017-01-18 19:50:4639}
40
41std::unique_ptr<FileMappedForLaunch>
42ChildProcessLauncherHelper::GetFilesToMap() {
Xi Han89d93df2018-03-09 20:55:0743 DCHECK(CurrentlyOnProcessLauncherTaskRunner());
Ken Rockot8dda88882019-12-04 05:56:2244 return CreateDefaultPosixFilesToMap(
Eriko Kurimoto9c83b402022-05-11 02:36:3245 child_process_id(), mojo_channel_->remote_endpoint(),
46 file_data_->files_to_preload, GetProcessType(), command_line());
jcivelli828cd7f2017-01-18 19:50:4647}
48
Matthew Denton7f7c1f52023-01-11 23:35:1249bool ChildProcessLauncherHelper::IsUsingLaunchOptions() {
Matthew Denton2bcef6172023-01-18 01:14:2450 return !GetZygoteForLaunch();
Matthew Denton7f7c1f52023-01-11 23:35:1251}
52
Greg Kerra1bc9d02018-01-04 23:22:3153bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
Lucas Furukawa Gadani0d5e7142019-04-18 23:00:5054 PosixFileDescriptorInfo& files_to_register,
jcivelli828cd7f2017-01-18 19:50:4655 base::LaunchOptions* options) {
Matthew Denton7f7c1f52023-01-11 23:35:1256 if (options) {
Matthew Denton2bcef6172023-01-18 01:14:2457 DCHECK(!GetZygoteForLaunch());
Matthew Denton7f7c1f52023-01-11 23:35:1258 // Convert FD mapping to FileHandleMappingVector
59 options->fds_to_remap = files_to_register.GetMappingWithIDAdjustment(
60 base::GlobalDescriptors::kBaseDescriptor);
jcivelli828cd7f2017-01-18 19:50:4661
Matthew Denton7f7c1f52023-01-11 23:35:1262 if (GetProcessType() == switches::kRendererProcess) {
63 const int sandbox_fd = SandboxHostLinux::GetInstance()->GetChildSocket();
64 options->fds_to_remap.emplace_back(sandbox_fd, GetSandboxFD());
65 }
66
67 options->environment = delegate_->GetEnvironment();
68 } else {
Matthew Denton2bcef6172023-01-18 01:14:2469 DCHECK(GetZygoteForLaunch());
Matthew Denton7f7c1f52023-01-11 23:35:1270 // Environment variables could be supported in the future, but are not
71 // currently supported when launching with the zygote.
72 DCHECK(delegate_->GetEnvironment().empty());
jcivelli828cd7f2017-01-18 19:50:4673 }
74
Greg Kerra1bc9d02018-01-04 23:22:3175 return true;
jcivelli828cd7f2017-01-18 19:50:4676}
77
78ChildProcessLauncherHelper::Process
79ChildProcessLauncherHelper::LaunchProcessOnLauncherThread(
Matthew Denton7f7c1f52023-01-11 23:35:1280 const base::LaunchOptions* options,
jcivelli828cd7f2017-01-18 19:50:4681 std::unique_ptr<FileMappedForLaunch> files_to_register,
82 bool* is_synchronous_launch,
83 int* launch_result) {
84 *is_synchronous_launch = true;
Youssef Esmatc732bf82022-05-27 00:47:1985 Process process;
Matthew Denton2bcef6172023-01-18 01:14:2486 ZygoteCommunication* zygote_handle = GetZygoteForLaunch();
jcivelli828cd7f2017-01-18 19:50:4687 if (zygote_handle) {
Alison Gale81f4f2c72024-04-22 19:33:3188 // TODO(crbug.com/40448989): If chrome supported multiple zygotes they could
jamescookca8595ad2017-05-01 16:58:3389 // be created lazily here, or in the delegate GetZygote() implementations.
90 // Additionally, the delegate could provide a UseGenericZygote() method.
91 base::ProcessHandle handle = zygote_handle->ForkRequest(
Tom Sepezf60832d2018-01-08 23:35:5092 command_line()->argv(), files_to_register->GetMapping(),
93 GetProcessType());
jcivelli828cd7f2017-01-18 19:50:4694 *launch_result = LAUNCH_RESULT_SUCCESS;
Tom Sepezd1a315b2018-01-11 18:18:0095
Xiaohan Wang1ecfd002022-01-19 22:33:1096#if !BUILDFLAG(IS_OPENBSD)
Tom Sepezd1a315b2018-01-11 18:18:0097 if (handle) {
Kuo-Hsin Yangbff00c72020-02-14 05:59:2398 // It could be a renderer process or an utility process.
99 int oom_score = content::kMiscOomScore;
100 if (command_line()->GetSwitchValueASCII(switches::kProcessType) ==
101 switches::kRendererProcess)
102 oom_score = content::kLowestRendererOomScore;
Robert Sesek8621aef02020-06-25 18:17:37103 ZygoteHostImpl::GetInstance()->AdjustRendererOOMScore(handle, oom_score);
Tom Sepezd1a315b2018-01-11 18:18:00104 }
105#endif
106
jcivelli828cd7f2017-01-18 19:50:46107 process.process = base::Process(handle);
jamescookca8595ad2017-05-01 16:58:33108 process.zygote = zygote_handle;
Youssef Esmatc732bf82022-05-27 00:47:19109 } else {
Matthew Denton7f7c1f52023-01-11 23:35:12110 process.process = base::LaunchProcess(*command_line(), *options);
Youssef Esmatc732bf82022-05-27 00:47:19111 *launch_result = process.process.IsValid() ? LAUNCH_RESULT_SUCCESS
112 : LAUNCH_RESULT_FAILURE;
jcivelli828cd7f2017-01-18 19:50:46113 }
114
Youssef Esmatc732bf82022-05-27 00:47:19115#if BUILDFLAG(IS_CHROMEOS)
Shintaro Kawamuraf726c1292024-03-28 03:40:08116 process_id_ = process.process.Pid();
117 if (GetProcessType() == switches::kRendererProcess ||
118 base::FeatureList::IsEnabled(features::kSchedQoSOnResourcedForChrome)) {
Youssef Esmatc732bf82022-05-27 00:47:19119 process.process.InitializePriority();
120 }
121#endif
122
jcivelli828cd7f2017-01-18 19:50:46123 return process;
124}
125
126void ChildProcessLauncherHelper::AfterLaunchOnLauncherThread(
127 const ChildProcessLauncherHelper::Process& process,
Matthew Denton7f7c1f52023-01-11 23:35:12128 const base::LaunchOptions* options) {
Matthew Dentonc46d14cb2023-01-11 00:59:21129 // Reset any FDs still held open.
130 file_data_.reset();
jcivelli828cd7f2017-01-18 19:50:46131}
132
Bo Liu0d2a2322018-04-19 00:18:09133ChildProcessTerminationInfo ChildProcessLauncherHelper::GetTerminationInfo(
jcivelli828cd7f2017-01-18 19:50:46134 const ChildProcessLauncherHelper::Process& process,
Bo Liu0d2a2322018-04-19 00:18:09135 bool known_dead) {
136 ChildProcessTerminationInfo info;
jcivelli828cd7f2017-01-18 19:50:46137 if (process.zygote) {
Bo Liu0d2a2322018-04-19 00:18:09138 info.status = process.zygote->GetTerminationStatus(
139 process.process.Handle(), known_dead, &info.exit_code);
140 } else if (known_dead) {
141 info.status = base::GetKnownDeadTerminationStatus(process.process.Handle(),
142 &info.exit_code);
143 } else {
144 info.status =
145 base::GetTerminationStatus(process.process.Handle(), &info.exit_code);
jcivelli828cd7f2017-01-18 19:50:46146 }
Bo Liu0d2a2322018-04-19 00:18:09147 return info;
jcivelli828cd7f2017-01-18 19:50:46148}
149
150// static
Wez0abfbf512018-03-03 01:54:45151bool ChildProcessLauncherHelper::TerminateProcess(const base::Process& process,
152 int exit_code) {
Alison Gale770f3fc2024-04-27 00:39:58153 // TODO(crbug.com/40565504): Determine whether we should also call
Wez0abfbf512018-03-03 01:54:45154 // EnsureProcessTerminated() to make sure of process-exit, and reap it.
155 return process.Terminate(exit_code, false);
jcivelli828cd7f2017-01-18 19:50:46156}
157
158// static
159void ChildProcessLauncherHelper::ForceNormalProcessTerminationSync(
160 ChildProcessLauncherHelper::Process process) {
Alexander Alekseev0df843b2023-08-09 13:33:15161 TRACE_EVENT0("chromeos",
162 "ChildProcessLauncherHelper::ForceNormalProcessTerminationSync");
Wezc18a57c2018-04-02 20:20:14163 DCHECK(CurrentlyOnProcessLauncherTaskRunner());
Ken Rockot1d00d6d02020-10-01 15:10:05164 process.process.Terminate(RESULT_CODE_NORMAL_EXIT, false);
jcivelli828cd7f2017-01-18 19:50:46165 // On POSIX, we must additionally reap the child.
166 if (process.zygote) {
167 // If the renderer was created via a zygote, we have to proxy the reaping
168 // through the zygote process.
169 process.zygote->EnsureProcessTerminated(process.process.Handle());
170 } else {
171 base::EnsureProcessTerminated(std::move(process.process));
172 }
173}
174
Patrick Monette20997a22023-08-07 17:30:17175void ChildProcessLauncherHelper::SetProcessPriorityOnLauncherThread(
boliu3e77d172017-05-11 04:56:04176 base::Process process,
Patrick Monette20997a22023-08-07 17:30:17177 base::Process::Priority priority) {
Xi Han89d93df2018-03-09 20:55:07178 DCHECK(CurrentlyOnProcessLauncherTaskRunner());
Patrick Monette7a8ca3862025-05-08 01:40:53179 if (process.CanSetPriority()) {
Patrick Monette20997a22023-08-07 17:30:17180 process.SetPriority(priority);
181 }
jcivelli828cd7f2017-01-18 19:50:46182}
183
Matthew Denton2bcef6172023-01-18 01:14:24184ZygoteCommunication* ChildProcessLauncherHelper::GetZygoteForLaunch() {
Matthew Denton7f7c1f52023-01-11 23:35:12185 return base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoZygote)
186 ? nullptr
187 : delegate_->GetZygote();
188}
189
jcivellidad0cef2017-02-16 18:38:59190base::File OpenFileToShare(const base::FilePath& path,
191 base::MemoryMappedFile::Region* region) {
192 base::FilePath exe_dir;
193 bool result = base::PathService::Get(base::BasePathKey::DIR_EXE, &exe_dir);
194 DCHECK(result);
195 base::File file(exe_dir.Append(path),
196 base::File::FLAG_OPEN | base::File::FLAG_READ);
197 *region = base::MemoryMappedFile::Region::kWholeFile;
198 return file;
199}
200
jcivelli828cd7f2017-01-18 19:50:46201} // namespace internal
202} // namespace content