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. 4 5 #include "content/zygote/zygote_linux.h" 6 7 #include <fcntl.h> 8 #include <string.h> 9 #include <sys/socket.h> 10 #include <sys/types.h> 11 #include <sys/wait.h> 12 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" 35 36 #if defined(ADDRESS_SANITIZER) 37 #include <sanitizer/asan_interface.h> 38 #endif 39 40 // See http://code.google.com/p/chromium/wiki/LinuxZygote 41 42 namespace content { 43 44 namespace { 45 46 // NOP function. See below where this handler is installed. 47 void SIGCHLDHandler(int signal) { 48 } 49 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; 54 } 55 return -1; 56 } 57 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]); 63 } 64 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; 74 } 75 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))); 80 } 81 82 } // namespace 83 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) {} 92 93 Zygote::~Zygote() { 94 } 95 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 101 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); 108 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 126 } 127 128 for (;;) { 129 // This function call can return multiple times, once per fork(). 130 if (HandleRequestFromBrowser(kZygoteSocketPairFd)) 131 return true; 132 } 133 } 134 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; 141 } 142 *process_info = it->second; 143 return true; 144 } 145 146 bool Zygote::UsingSUIDSandbox() const { 147 return sandbox_flags_ & kSandboxLinuxSUID; 148 } 149 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); 154 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))); 163 } 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))); 172 } 173 _exit(0); 174 return false; 175 } 176 177 if (len == -1) { 178 PLOG(ERROR) << "Error reading message from browser"; 179 return false; 180 } 181 182 Pickle pickle(buf, len); 183 PickleIterator iter(pickle); 184 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()); 191 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; 215 } 216 } 217 218 LOG(WARNING) << "Error parsing message from browser"; 219 return false; 220 } 221 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; 227 228 if (!pickle.ReadInt(&iter, &child)) { 229 LOG(WARNING) << "Error parsing reap request from browser"; 230 return; 231 } 232 233 ZygoteProcessInfo child_info; 234 if (!GetProcessInfo(child, &child_info)) { 235 LOG(ERROR) << "Child not found!"; 236 NOTREACHED(); 237 return; 238 } 239 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); 266 } 267 process_info_map_.erase(child); 268 } 269 270 bool Zygote::GetTerminationStatus(base::ProcessHandle real_pid, 271 bool known_dead, 272 base::TerminationStatus* status, 273 int* exit_code) { 274 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; 281 } 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; 288 } 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); 297 } 298 } 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); 303 } 304 return true; 305 } 306 307 void Zygote::HandleGetTerminationStatus(int fd, 308 const Pickle& pickle, 309 PickleIterator iter) { 310 bool known_dead; 311 base::ProcessHandle child_requested; 312 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; 318 } 319 320 base::TerminationStatus status; 321 int exit_code; 322 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; 331 } 332 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"; 340 } 341 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; 356 } 357 } 358 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; 366 } 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); 371 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(); 377 } 378 379 if (pid == 0) { 380 // In the child process. 381 write_pipe.reset(); 382 383 // Ping the PID oracle socket so the browser can find our PID. 384 CHECK(SendZygoteChildPing(pid_oracle.get())); 385 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"; 392 } 393 if (real_pid <= 0) { 394 LOG(FATAL) << "Invalid pid from parent zygote"; 395 } 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; 406 } 407 408 // In the parent process. 409 read_pipe.reset(); 410 pid_oracle.reset(); 411 412 // Always receive a real PID from the zygote host, though it might 413 // be invalid (see below). 414 base::ProcessId real_pid; 415 { 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()); 422 423 Pickle pickle(buf, len); 424 PickleIterator iter(pickle); 425 426 int kind; 427 CHECK(pickle.ReadInt(&iter, &kind)); 428 CHECK(kind == kZygoteCommandForkRealPID); 429 CHECK(pickle.ReadInt(&iter, &real_pid)); 430 } 431 432 // Fork failed. 433 if (pid < 0) { 434 return -1; 435 } 436 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; 442 } 443 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; 451 } 452 } 453 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(); 458 } 459 process_info_map_[real_pid].internal_pid = pid; 460 process_info_map_[real_pid].started_from_helper = helper; 461 462 return real_pid; 463 } 464 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("="); 479 480 if (!pickle.ReadString(&iter, &process_type)) 481 return -1; 482 if (!pickle.ReadInt(&iter, &argc)) 483 return -1; 484 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()); 492 } 493 494 if (!pickle.ReadInt(&iter, &numfds)) 495 return -1; 496 if (numfds != static_cast<int>(fds.size())) 497 return -1; 498 499 // First FD is the PID oracle socket. 500 if (fds.size() < 1) 501 return -1; 502 base::ScopedFD pid_oracle(fds[0]->Pass()); 503 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())); 510 } 511 512 mapping.push_back(std::make_pair( 513 static_cast<uint32_t>(kSandboxIPCChannel), GetSandboxFD())); 514 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. 525 526 // Our socket from the browser. 527 PCHECK(0 == IGNORE_EINTR(close(kZygoteSocketPairFd))); 528 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); 534 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); 539 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; 547 } 548 return child_pid; 549 } 550 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); 567 } 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); 575 } 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; 580 } 581 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"; 588 } 589 590 return false; 591 } 592 593 } // namespace content 594