Trust the renderer's same-document navigation flag if it is a same-origin nav.
[chromium-blink-merge.git] / content / zygote / zygote_linux.cc
blobe5e91296da7bc1873c9d25e6ee9a8a51ab3faed2
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/zygote/zygote_linux.h"
7 #include <fcntl.h>
8 #include <string.h>
9 #include <sys/socket.h>
10 #include <sys/types.h>
11 #include <sys/wait.h>
13 #include "base/command_line.h"
14 #include "base/debug/trace_event.h"
15 #include "base/file_util.h"
16 #include "base/linux_util.h"
17 #include "base/logging.h"
18 #include "base/macros.h"
19 #include "base/memory/scoped_vector.h"
20 #include "base/pickle.h"
21 #include "base/posix/eintr_wrapper.h"
22 #include "base/posix/global_descriptors.h"
23 #include "base/posix/unix_domain_socket_linux.h"
24 #include "base/process/kill.h"
25 #include "content/common/child_process_sandbox_support_impl_linux.h"
26 #include "content/common/sandbox_linux/sandbox_linux.h"
27 #include "content/common/set_process_title.h"
28 #include "content/common/zygote_commands_linux.h"
29 #include "content/public/common/content_descriptors.h"
30 #include "content/public/common/result_codes.h"
31 #include "content/public/common/sandbox_linux.h"
32 #include "content/public/common/zygote_fork_delegate_linux.h"
33 #include "ipc/ipc_channel.h"
34 #include "ipc/ipc_switches.h"
36 #if defined(ADDRESS_SANITIZER)
37 #include <sanitizer/asan_interface.h>
38 #endif
40 // See http://code.google.com/p/chromium/wiki/LinuxZygote
42 namespace content {
44 namespace {
46 // NOP function. See below where this handler is installed.
47 void SIGCHLDHandler(int signal) {
50 int LookUpFd(const base::GlobalDescriptors::Mapping& fd_mapping, uint32_t key) {
51 for (size_t index = 0; index < fd_mapping.size(); ++index) {
52 if (fd_mapping[index].first == key)
53 return fd_mapping[index].second;
55 return -1;
58 void CreatePipe(base::ScopedFD* read_pipe, base::ScopedFD* write_pipe) {
59 int raw_pipe[2];
60 PCHECK(0 == pipe(raw_pipe));
61 read_pipe->reset(raw_pipe[0]);
62 write_pipe->reset(raw_pipe[1]);
65 void KillAndReap(pid_t pid, ZygoteForkDelegate* helper) {
66 if (helper) {
67 // Helper children may be forked in another PID namespace, so |pid| might
68 // be meaningless to us; or we just might not be able to directly send it
69 // signals. So we can't kill it.
70 // Additionally, we're not its parent, so we can't reap it anyway.
71 // TODO(mdempsky): Extend the ZygoteForkDelegate API to handle this.
72 LOG(WARNING) << "Unable to kill or reap helper children";
73 return;
76 // Kill the child process in case it's not already dead, so we can safely
77 // perform a blocking wait.
78 PCHECK(0 == kill(pid, SIGKILL));
79 PCHECK(pid == HANDLE_EINTR(waitpid(pid, NULL, 0)));
82 } // namespace
84 Zygote::Zygote(int sandbox_flags, ScopedVector<ZygoteForkDelegate> helpers,
85 const std::vector<base::ProcessHandle>& extra_children,
86 const std::vector<int>& extra_fds)
87 : sandbox_flags_(sandbox_flags),
88 helpers_(helpers.Pass()),
89 initial_uma_index_(0),
90 extra_children_(extra_children),
91 extra_fds_(extra_fds) {}
93 Zygote::~Zygote() {
96 bool Zygote::ProcessRequests() {
97 // A SOCK_SEQPACKET socket is installed in fd 3. We get commands from the
98 // browser on it.
99 // A SOCK_DGRAM is installed in fd 5. This is the sandbox IPC channel.
100 // See http://code.google.com/p/chromium/wiki/LinuxSandboxIPC
102 // We need to accept SIGCHLD, even though our handler is a no-op because
103 // otherwise we cannot wait on children. (According to POSIX 2001.)
104 struct sigaction action;
105 memset(&action, 0, sizeof(action));
106 action.sa_handler = &SIGCHLDHandler;
107 CHECK(sigaction(SIGCHLD, &action, NULL) == 0);
109 if (UsingSUIDSandbox()) {
110 // Let the ZygoteHost know we are ready to go.
111 // The receiving code is in content/browser/zygote_host_linux.cc.
112 bool r = UnixDomainSocket::SendMsg(kZygoteSocketPairFd,
113 kZygoteHelloMessage,
114 sizeof(kZygoteHelloMessage),
115 std::vector<int>());
116 #if defined(OS_CHROMEOS)
117 LOG_IF(WARNING, !r) << "Sending zygote magic failed";
118 // Exit normally on chromeos because session manager may send SIGTERM
119 // right after the process starts and it may fail to send zygote magic
120 // number to browser process.
121 if (!r)
122 _exit(RESULT_CODE_NORMAL_EXIT);
123 #else
124 CHECK(r) << "Sending zygote magic failed";
125 #endif
128 for (;;) {
129 // This function call can return multiple times, once per fork().
130 if (HandleRequestFromBrowser(kZygoteSocketPairFd))
131 return true;
135 bool Zygote::GetProcessInfo(base::ProcessHandle pid,
136 ZygoteProcessInfo* process_info) {
137 DCHECK(process_info);
138 const ZygoteProcessMap::const_iterator it = process_info_map_.find(pid);
139 if (it == process_info_map_.end()) {
140 return false;
142 *process_info = it->second;
143 return true;
146 bool Zygote::UsingSUIDSandbox() const {
147 return sandbox_flags_ & kSandboxLinuxSUID;
150 bool Zygote::HandleRequestFromBrowser(int fd) {
151 ScopedVector<base::ScopedFD> fds;
152 char buf[kZygoteMaxMessageLength];
153 const ssize_t len = UnixDomainSocket::RecvMsg(fd, buf, sizeof(buf), &fds);
155 if (len == 0 || (len == -1 && errno == ECONNRESET)) {
156 // EOF from the browser. We should die.
157 // TODO(earthdok): call __sanititizer_cov_dump() here to obtain code
158 // coverage for the Zygote. Currently it's not possible because of
159 // confusion over who is responsible for closing the file descriptor.
160 for (std::vector<int>::iterator it = extra_fds_.begin();
161 it < extra_fds_.end(); ++it) {
162 PCHECK(0 == IGNORE_EINTR(close(*it)));
164 #if !defined(ADDRESS_SANITIZER)
165 // TODO(earthdok): add watchdog thread before using this in non-ASAN builds.
166 CHECK(extra_children_.empty());
167 #endif
168 for (std::vector<base::ProcessHandle>::iterator it =
169 extra_children_.begin();
170 it < extra_children_.end(); ++it) {
171 PCHECK(*it == HANDLE_EINTR(waitpid(*it, NULL, 0)));
173 _exit(0);
174 return false;
177 if (len == -1) {
178 PLOG(ERROR) << "Error reading message from browser";
179 return false;
182 Pickle pickle(buf, len);
183 PickleIterator iter(pickle);
185 int kind;
186 if (pickle.ReadInt(&iter, &kind)) {
187 switch (kind) {
188 case kZygoteCommandFork:
189 // This function call can return multiple times, once per fork().
190 return HandleForkRequest(fd, pickle, iter, fds.Pass());
192 case kZygoteCommandReap:
193 if (!fds.empty())
194 break;
195 HandleReapRequest(fd, pickle, iter);
196 return false;
197 case kZygoteCommandGetTerminationStatus:
198 if (!fds.empty())
199 break;
200 HandleGetTerminationStatus(fd, pickle, iter);
201 return false;
202 case kZygoteCommandGetSandboxStatus:
203 HandleGetSandboxStatus(fd, pickle, iter);
204 return false;
205 case kZygoteCommandForkRealPID:
206 // This shouldn't happen in practice, but some failure paths in
207 // HandleForkRequest (e.g., if ReadArgsAndFork fails during depickling)
208 // could leave this command pending on the socket.
209 LOG(ERROR) << "Unexpected real PID message from browser";
210 NOTREACHED();
211 return false;
212 default:
213 NOTREACHED();
214 break;
218 LOG(WARNING) << "Error parsing message from browser";
219 return false;
222 // TODO(jln): remove callers to this broken API. See crbug.com/274855.
223 void Zygote::HandleReapRequest(int fd,
224 const Pickle& pickle,
225 PickleIterator iter) {
226 base::ProcessId child;
228 if (!pickle.ReadInt(&iter, &child)) {
229 LOG(WARNING) << "Error parsing reap request from browser";
230 return;
233 ZygoteProcessInfo child_info;
234 if (!GetProcessInfo(child, &child_info)) {
235 LOG(ERROR) << "Child not found!";
236 NOTREACHED();
237 return;
240 if (!child_info.started_from_helper) {
241 // Do not call base::EnsureProcessTerminated() under ThreadSanitizer, as it
242 // spawns a separate thread which may live until the call to fork() in the
243 // zygote. As a result, ThreadSanitizer will report an error and almost
244 // disable race detection in the child process.
245 // Not calling EnsureProcessTerminated() may result in zombie processes
246 // sticking around. This will only happen during testing, so we can live
247 // with this for now.
248 #if !defined(THREAD_SANITIZER)
249 // TODO(jln): this old code is completely broken. See crbug.com/274855.
250 base::EnsureProcessTerminated(child_info.internal_pid);
251 #else
252 LOG(WARNING) << "Zygote process omitting a call to "
253 << "base::EnsureProcessTerminated() for child pid " << child
254 << " under ThreadSanitizer. See http://crbug.com/274855.";
255 #endif
256 } else {
257 // For processes from the helper, send a GetTerminationStatus request
258 // with known_dead set to true.
259 // This is not perfect, as the process may be killed instantly, but is
260 // better than ignoring the request.
261 base::TerminationStatus status;
262 int exit_code;
263 bool got_termination_status =
264 GetTerminationStatus(child, true /* known_dead */, &status, &exit_code);
265 DCHECK(got_termination_status);
267 process_info_map_.erase(child);
270 bool Zygote::GetTerminationStatus(base::ProcessHandle real_pid,
271 bool known_dead,
272 base::TerminationStatus* status,
273 int* exit_code) {
275 ZygoteProcessInfo child_info;
276 if (!GetProcessInfo(real_pid, &child_info)) {
277 LOG(ERROR) << "Zygote::GetTerminationStatus for unknown PID "
278 << real_pid;
279 NOTREACHED();
280 return false;
282 // We know about |real_pid|.
283 const base::ProcessHandle child = child_info.internal_pid;
284 if (child_info.started_from_helper) {
285 if (!child_info.started_from_helper->GetTerminationStatus(
286 child, known_dead, status, exit_code)) {
287 return false;
289 } else {
290 // Handle the request directly.
291 if (known_dead) {
292 *status = base::GetKnownDeadTerminationStatus(child, exit_code);
293 } else {
294 // We don't know if the process is dying, so get its status but don't
295 // wait.
296 *status = base::GetTerminationStatus(child, exit_code);
299 // Successfully got a status for |real_pid|.
300 if (*status != base::TERMINATION_STATUS_STILL_RUNNING) {
301 // Time to forget about this process.
302 process_info_map_.erase(real_pid);
304 return true;
307 void Zygote::HandleGetTerminationStatus(int fd,
308 const Pickle& pickle,
309 PickleIterator iter) {
310 bool known_dead;
311 base::ProcessHandle child_requested;
313 if (!pickle.ReadBool(&iter, &known_dead) ||
314 !pickle.ReadInt(&iter, &child_requested)) {
315 LOG(WARNING) << "Error parsing GetTerminationStatus request "
316 << "from browser";
317 return;
320 base::TerminationStatus status;
321 int exit_code;
323 bool got_termination_status =
324 GetTerminationStatus(child_requested, known_dead, &status, &exit_code);
325 if (!got_termination_status) {
326 // Assume that if we can't find the child in the sandbox, then
327 // it terminated normally.
328 NOTREACHED();
329 status = base::TERMINATION_STATUS_NORMAL_TERMINATION;
330 exit_code = RESULT_CODE_NORMAL_EXIT;
333 Pickle write_pickle;
334 write_pickle.WriteInt(static_cast<int>(status));
335 write_pickle.WriteInt(exit_code);
336 ssize_t written =
337 HANDLE_EINTR(write(fd, write_pickle.data(), write_pickle.size()));
338 if (written != static_cast<ssize_t>(write_pickle.size()))
339 PLOG(ERROR) << "write";
342 int Zygote::ForkWithRealPid(const std::string& process_type,
343 const base::GlobalDescriptors::Mapping& fd_mapping,
344 const std::string& channel_id,
345 base::ScopedFD pid_oracle,
346 std::string* uma_name,
347 int* uma_sample,
348 int* uma_boundary_value) {
349 ZygoteForkDelegate* helper = NULL;
350 for (ScopedVector<ZygoteForkDelegate>::iterator i = helpers_.begin();
351 i != helpers_.end();
352 ++i) {
353 if ((*i)->CanHelp(process_type, uma_name, uma_sample, uma_boundary_value)) {
354 helper = *i;
355 break;
359 base::ScopedFD read_pipe, write_pipe;
360 base::ProcessId pid = 0;
361 if (helper) {
362 int ipc_channel_fd = LookUpFd(fd_mapping, kPrimaryIPCChannel);
363 if (ipc_channel_fd < 0) {
364 DLOG(ERROR) << "Failed to find kPrimaryIPCChannel in FD mapping";
365 return -1;
367 std::vector<int> fds;
368 fds.push_back(ipc_channel_fd); // kBrowserFDIndex
369 fds.push_back(pid_oracle.get()); // kPIDOracleFDIndex
370 pid = helper->Fork(process_type, fds, channel_id);
372 // Helpers should never return in the child process.
373 CHECK_NE(pid, 0);
374 } else {
375 CreatePipe(&read_pipe, &write_pipe);
376 pid = fork();
379 if (pid == 0) {
380 // In the child process.
381 write_pipe.reset();
383 // Ping the PID oracle socket so the browser can find our PID.
384 CHECK(SendZygoteChildPing(pid_oracle.get()));
386 // Now read back our real PID from the zygote.
387 base::ProcessId real_pid;
388 if (!base::ReadFromFD(read_pipe.get(),
389 reinterpret_cast<char*>(&real_pid),
390 sizeof(real_pid))) {
391 LOG(FATAL) << "Failed to synchronise with parent zygote process";
393 if (real_pid <= 0) {
394 LOG(FATAL) << "Invalid pid from parent zygote";
396 #if defined(OS_LINUX)
397 // Sandboxed processes need to send the global, non-namespaced PID when
398 // setting up an IPC channel to their parent.
399 IPC::Channel::SetGlobalPid(real_pid);
400 // Force the real PID so chrome event data have a PID that corresponds
401 // to system trace event data.
402 base::debug::TraceLog::GetInstance()->SetProcessID(
403 static_cast<int>(real_pid));
404 #endif
405 return 0;
408 // In the parent process.
409 read_pipe.reset();
410 pid_oracle.reset();
412 // Always receive a real PID from the zygote host, though it might
413 // be invalid (see below).
414 base::ProcessId real_pid;
416 ScopedVector<base::ScopedFD> recv_fds;
417 char buf[kZygoteMaxMessageLength];
418 const ssize_t len = UnixDomainSocket::RecvMsg(
419 kZygoteSocketPairFd, buf, sizeof(buf), &recv_fds);
420 CHECK_GT(len, 0);
421 CHECK(recv_fds.empty());
423 Pickle pickle(buf, len);
424 PickleIterator iter(pickle);
426 int kind;
427 CHECK(pickle.ReadInt(&iter, &kind));
428 CHECK(kind == kZygoteCommandForkRealPID);
429 CHECK(pickle.ReadInt(&iter, &real_pid));
432 // Fork failed.
433 if (pid < 0) {
434 return -1;
437 // If we successfully forked a child, but it crashed without sending
438 // a message to the browser, the browser won't have found its PID.
439 if (real_pid < 0) {
440 KillAndReap(pid, helper);
441 return -1;
444 // If we're not using a helper, send the PID back to the child process.
445 if (!helper) {
446 ssize_t written =
447 HANDLE_EINTR(write(write_pipe.get(), &real_pid, sizeof(real_pid)));
448 if (written != sizeof(real_pid)) {
449 KillAndReap(pid, helper);
450 return -1;
454 // Now set-up this process to be tracked by the Zygote.
455 if (process_info_map_.find(real_pid) != process_info_map_.end()) {
456 LOG(ERROR) << "Already tracking PID " << real_pid;
457 NOTREACHED();
459 process_info_map_[real_pid].internal_pid = pid;
460 process_info_map_[real_pid].started_from_helper = helper;
462 return real_pid;
465 base::ProcessId Zygote::ReadArgsAndFork(const Pickle& pickle,
466 PickleIterator iter,
467 ScopedVector<base::ScopedFD> fds,
468 std::string* uma_name,
469 int* uma_sample,
470 int* uma_boundary_value) {
471 std::vector<std::string> args;
472 int argc = 0;
473 int numfds = 0;
474 base::GlobalDescriptors::Mapping mapping;
475 std::string process_type;
476 std::string channel_id;
477 const std::string channel_id_prefix = std::string("--")
478 + switches::kProcessChannelID + std::string("=");
480 if (!pickle.ReadString(&iter, &process_type))
481 return -1;
482 if (!pickle.ReadInt(&iter, &argc))
483 return -1;
485 for (int i = 0; i < argc; ++i) {
486 std::string arg;
487 if (!pickle.ReadString(&iter, &arg))
488 return -1;
489 args.push_back(arg);
490 if (arg.compare(0, channel_id_prefix.length(), channel_id_prefix) == 0)
491 channel_id = arg.substr(channel_id_prefix.length());
494 if (!pickle.ReadInt(&iter, &numfds))
495 return -1;
496 if (numfds != static_cast<int>(fds.size()))
497 return -1;
499 // First FD is the PID oracle socket.
500 if (fds.size() < 1)
501 return -1;
502 base::ScopedFD pid_oracle(fds[0]->Pass());
504 // Remaining FDs are for the global descriptor mapping.
505 for (int i = 1; i < numfds; ++i) {
506 base::GlobalDescriptors::Key key;
507 if (!pickle.ReadUInt32(&iter, &key))
508 return -1;
509 mapping.push_back(std::make_pair(key, fds[i]->get()));
512 mapping.push_back(std::make_pair(
513 static_cast<uint32_t>(kSandboxIPCChannel), GetSandboxFD()));
515 // Returns twice, once per process.
516 base::ProcessId child_pid = ForkWithRealPid(process_type,
517 mapping,
518 channel_id,
519 pid_oracle.Pass(),
520 uma_name,
521 uma_sample,
522 uma_boundary_value);
523 if (!child_pid) {
524 // This is the child process.
526 // Our socket from the browser.
527 PCHECK(0 == IGNORE_EINTR(close(kZygoteSocketPairFd)));
529 // Pass ownership of file descriptors from fds to GlobalDescriptors.
530 for (ScopedVector<base::ScopedFD>::iterator i = fds.begin(); i != fds.end();
531 ++i)
532 ignore_result((*i)->release());
533 base::GlobalDescriptors::GetInstance()->Reset(mapping);
535 // Reset the process-wide command line to our new command line.
536 CommandLine::Reset();
537 CommandLine::Init(0, NULL);
538 CommandLine::ForCurrentProcess()->InitFromArgv(args);
540 // Update the process title. The argv was already cached by the call to
541 // SetProcessTitleFromCommandLine in ChromeMain, so we can pass NULL here
542 // (we don't have the original argv at this point).
543 SetProcessTitleFromCommandLine(NULL);
544 } else if (child_pid < 0) {
545 LOG(ERROR) << "Zygote could not fork: process_type " << process_type
546 << " numfds " << numfds << " child_pid " << child_pid;
548 return child_pid;
551 bool Zygote::HandleForkRequest(int fd,
552 const Pickle& pickle,
553 PickleIterator iter,
554 ScopedVector<base::ScopedFD> fds) {
555 std::string uma_name;
556 int uma_sample;
557 int uma_boundary_value;
558 base::ProcessId child_pid = ReadArgsAndFork(
559 pickle, iter, fds.Pass(), &uma_name, &uma_sample, &uma_boundary_value);
560 if (child_pid == 0)
561 return true;
562 // If there's no UMA report for this particular fork, then check if any
563 // helpers have an initial UMA report for us to send instead.
564 while (uma_name.empty() && initial_uma_index_ < helpers_.size()) {
565 helpers_[initial_uma_index_++]->InitialUMA(
566 &uma_name, &uma_sample, &uma_boundary_value);
568 // Must always send reply, as ZygoteHost blocks while waiting for it.
569 Pickle reply_pickle;
570 reply_pickle.WriteInt(child_pid);
571 reply_pickle.WriteString(uma_name);
572 if (!uma_name.empty()) {
573 reply_pickle.WriteInt(uma_sample);
574 reply_pickle.WriteInt(uma_boundary_value);
576 if (HANDLE_EINTR(write(fd, reply_pickle.data(), reply_pickle.size())) !=
577 static_cast<ssize_t> (reply_pickle.size()))
578 PLOG(ERROR) << "write";
579 return false;
582 bool Zygote::HandleGetSandboxStatus(int fd,
583 const Pickle& pickle,
584 PickleIterator iter) {
585 if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_))) !=
586 sizeof(sandbox_flags_)) {
587 PLOG(ERROR) << "write";
590 return false;
593 } // namespace content