| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/zygote/zygote_main.h" | 5 #include "content/zygote/zygote_main.h" |
| 6 | 6 |
| 7 #include <dlfcn.h> | 7 #include <dlfcn.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <pthread.h> | 9 #include <pthread.h> |
| 10 #include <signal.h> | 10 #include <signal.h> |
| 11 #include <string.h> | 11 #include <string.h> |
| 12 #include <sys/socket.h> | 12 #include <sys/socket.h> |
| 13 #include <sys/types.h> | 13 #include <sys/types.h> |
| 14 #include <unistd.h> | 14 #include <unistd.h> |
| 15 | 15 |
| 16 #include <vector> |
| 17 |
| 16 #include "base/basictypes.h" | 18 #include "base/basictypes.h" |
| 17 #include "base/bind.h" | 19 #include "base/bind.h" |
| 18 #include "base/command_line.h" | 20 #include "base/command_line.h" |
| 19 #include "base/compiler_specific.h" | 21 #include "base/compiler_specific.h" |
| 20 #include "base/memory/scoped_vector.h" | 22 #include "base/memory/scoped_vector.h" |
| 21 #include "base/native_library.h" | 23 #include "base/native_library.h" |
| 22 #include "base/pickle.h" | 24 #include "base/pickle.h" |
| 23 #include "base/posix/eintr_wrapper.h" | 25 #include "base/posix/eintr_wrapper.h" |
| 24 #include "base/posix/unix_domain_socket_linux.h" | 26 #include "base/posix/unix_domain_socket_linux.h" |
| 25 #include "base/rand_util.h" | 27 #include "base/rand_util.h" |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 // trigger a SIGSYS signal whose handler will crash. | 96 // trigger a SIGSYS signal whose handler will crash. |
| 95 // This has been added during the investigation of https://crbug.com/415842. | 97 // This has been added during the investigation of https://crbug.com/415842. |
| 96 void InstallSandboxCrashTestHandler() { | 98 void InstallSandboxCrashTestHandler() { |
| 97 struct sigaction act = {}; | 99 struct sigaction act = {}; |
| 98 act.sa_handler = DoChrootSignalHandler; | 100 act.sa_handler = DoChrootSignalHandler; |
| 99 CHECK_EQ(0, sigemptyset(&act.sa_mask)); | 101 CHECK_EQ(0, sigemptyset(&act.sa_mask)); |
| 100 act.sa_flags = 0; | 102 act.sa_flags = 0; |
| 101 | 103 |
| 102 PCHECK(0 == sigaction(SIGUSR2, &act, NULL)); | 104 PCHECK(0 == sigaction(SIGUSR2, &act, NULL)); |
| 103 } | 105 } |
| 106 |
| 107 void CloseFds(const std::vector<int>& fds) { |
| 108 for (const auto& it : fds) { |
| 109 PCHECK(0 == IGNORE_EINTR(close(it))); |
| 110 } |
| 111 } |
| 112 |
| 104 } // namespace | 113 } // namespace |
| 105 | 114 |
| 106 // See http://code.google.com/p/chromium/wiki/LinuxZygote | 115 // See http://code.google.com/p/chromium/wiki/LinuxZygote |
| 107 | 116 |
| 108 static void ProxyLocaltimeCallToBrowser(time_t input, struct tm* output, | 117 static void ProxyLocaltimeCallToBrowser(time_t input, struct tm* output, |
| 109 char* timezone_out, | 118 char* timezone_out, |
| 110 size_t timezone_out_len) { | 119 size_t timezone_out_len) { |
| 111 Pickle request; | 120 Pickle request; |
| 112 request.WriteInt(LinuxSandbox::METHOD_LOCALTIME); | 121 request.WriteInt(LinuxSandbox::METHOD_LOCALTIME); |
| 113 request.WriteString( | 122 request.WriteString( |
| (...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 487 } | 496 } |
| 488 } | 497 } |
| 489 | 498 |
| 490 // fds[0] is the read end, fds[1] is the write end. | 499 // fds[0] is the read end, fds[1] is the write end. |
| 491 static void CreateSanitizerCoverageSocketPair(int fds[2]) { | 500 static void CreateSanitizerCoverageSocketPair(int fds[2]) { |
| 492 PCHECK(0 == socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds)); | 501 PCHECK(0 == socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds)); |
| 493 PCHECK(0 == shutdown(fds[0], SHUT_WR)); | 502 PCHECK(0 == shutdown(fds[0], SHUT_WR)); |
| 494 PCHECK(0 == shutdown(fds[1], SHUT_RD)); | 503 PCHECK(0 == shutdown(fds[1], SHUT_RD)); |
| 495 } | 504 } |
| 496 | 505 |
| 497 static pid_t ForkSanitizerCoverageHelper(int child_fd, int parent_fd, | 506 static pid_t ForkSanitizerCoverageHelper( |
| 498 base::ScopedFD file_fd) { | 507 int child_fd, |
| 508 int parent_fd, |
| 509 base::ScopedFD file_fd, |
| 510 const std::vector<int>& extra_fds_to_close) { |
| 499 pid_t pid = fork(); | 511 pid_t pid = fork(); |
| 500 PCHECK(pid >= 0); | 512 PCHECK(pid >= 0); |
| 501 if (pid == 0) { | 513 if (pid == 0) { |
| 502 // In the child. | 514 // In the child. |
| 503 PCHECK(0 == IGNORE_EINTR(close(parent_fd))); | 515 PCHECK(0 == IGNORE_EINTR(close(parent_fd))); |
| 516 CloseFds(extra_fds_to_close); |
| 504 SanitizerCoverageHelper(child_fd, file_fd.get()); | 517 SanitizerCoverageHelper(child_fd, file_fd.get()); |
| 505 _exit(0); | 518 _exit(0); |
| 506 } else { | 519 } else { |
| 507 // In the parent. | 520 // In the parent. |
| 508 PCHECK(0 == IGNORE_EINTR(close(child_fd))); | 521 PCHECK(0 == IGNORE_EINTR(close(child_fd))); |
| 509 return pid; | 522 return pid; |
| 510 } | 523 } |
| 511 } | 524 } |
| 512 | 525 |
| 513 void CloseFdPair(const int fds[2]) { | |
| 514 PCHECK(0 == IGNORE_EINTR(close(fds[0]))); | |
| 515 PCHECK(0 == IGNORE_EINTR(close(fds[1]))); | |
| 516 } | |
| 517 #endif // defined(ADDRESS_SANITIZER) | 526 #endif // defined(ADDRESS_SANITIZER) |
| 518 | 527 |
| 519 // If |is_suid_sandbox_child|, then make sure that the setuid sandbox is | 528 // If |is_suid_sandbox_child|, then make sure that the setuid sandbox is |
| 520 // engaged. | 529 // engaged. |
| 521 static void EnterLayerOneSandbox(LinuxSandbox* linux_sandbox, | 530 static void EnterLayerOneSandbox(LinuxSandbox* linux_sandbox, |
| 522 bool is_suid_sandbox_child, | 531 bool is_suid_sandbox_child, |
| 523 base::Closure* post_fork_parent_callback) { | 532 base::Closure* post_fork_parent_callback) { |
| 524 DCHECK(linux_sandbox); | 533 DCHECK(linux_sandbox); |
| 525 | 534 |
| 526 ZygotePreSandboxInit(); | 535 ZygotePreSandboxInit(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 537 CHECK(EnterSuidSandbox(setuid_sandbox, post_fork_parent_callback)) | 546 CHECK(EnterSuidSandbox(setuid_sandbox, post_fork_parent_callback)) |
| 538 << "Failed to enter setuid sandbox"; | 547 << "Failed to enter setuid sandbox"; |
| 539 } | 548 } |
| 540 } | 549 } |
| 541 | 550 |
| 542 bool ZygoteMain(const MainFunctionParams& params, | 551 bool ZygoteMain(const MainFunctionParams& params, |
| 543 ScopedVector<ZygoteForkDelegate> fork_delegates) { | 552 ScopedVector<ZygoteForkDelegate> fork_delegates) { |
| 544 g_am_zygote_or_renderer = true; | 553 g_am_zygote_or_renderer = true; |
| 545 sandbox::InitLibcUrandomOverrides(); | 554 sandbox::InitLibcUrandomOverrides(); |
| 546 | 555 |
| 547 base::Closure *post_fork_parent_callback = NULL; | 556 std::vector<int> fds_to_close_post_fork; |
| 548 | 557 |
| 549 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); | 558 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); |
| 550 | 559 |
| 551 #if defined(ADDRESS_SANITIZER) | 560 #if defined(ADDRESS_SANITIZER) |
| 552 const std::string sancov_file_name = | 561 const std::string sancov_file_name = |
| 553 "zygote." + base::Uint64ToString(base::RandUint64()); | 562 "zygote." + base::Uint64ToString(base::RandUint64()); |
| 554 base::ScopedFD sancov_file_fd( | 563 base::ScopedFD sancov_file_fd( |
| 555 __sanitizer_maybe_open_cov_file(sancov_file_name.c_str())); | 564 __sanitizer_maybe_open_cov_file(sancov_file_name.c_str())); |
| 556 int sancov_socket_fds[2] = {-1, -1}; | 565 int sancov_socket_fds[2] = {-1, -1}; |
| 557 CreateSanitizerCoverageSocketPair(sancov_socket_fds); | 566 CreateSanitizerCoverageSocketPair(sancov_socket_fds); |
| 558 linux_sandbox->sanitizer_args()->coverage_sandboxed = 1; | 567 linux_sandbox->sanitizer_args()->coverage_sandboxed = 1; |
| 559 linux_sandbox->sanitizer_args()->coverage_fd = sancov_socket_fds[1]; | 568 linux_sandbox->sanitizer_args()->coverage_fd = sancov_socket_fds[1]; |
| 560 linux_sandbox->sanitizer_args()->coverage_max_block_size = | 569 linux_sandbox->sanitizer_args()->coverage_max_block_size = |
| 561 kSanitizerMaxMessageLength; | 570 kSanitizerMaxMessageLength; |
| 562 // Zygote termination will block until the helper process exits, which will | 571 // Zygote termination will block until the helper process exits, which will |
| 563 // not happen until the write end of the socket is closed everywhere. Make | 572 // not happen until the write end of the socket is closed everywhere. Make |
| 564 // sure the init process does not hold on to it. | 573 // sure the init process does not hold on to it. |
| 565 base::Closure close_sancov_socket_fds = | 574 fds_to_close_post_fork.push_back(sancov_socket_fds[0]); |
| 566 base::Bind(&CloseFdPair, sancov_socket_fds); | 575 fds_to_close_post_fork.push_back(sancov_socket_fds[1]); |
| 567 post_fork_parent_callback = &close_sancov_socket_fds; | |
| 568 #endif | 576 #endif |
| 569 | 577 |
| 570 // This will pre-initialize the various sandboxes that need it. | 578 // This will pre-initialize the various sandboxes that need it. |
| 571 linux_sandbox->PreinitializeSandbox(); | 579 linux_sandbox->PreinitializeSandbox(); |
| 572 | 580 |
| 573 const bool must_enable_setuid_sandbox = | 581 const bool must_enable_setuid_sandbox = |
| 574 linux_sandbox->setuid_sandbox_client()->IsSuidSandboxChild(); | 582 linux_sandbox->setuid_sandbox_client()->IsSuidSandboxChild(); |
| 575 if (must_enable_setuid_sandbox) { | 583 if (must_enable_setuid_sandbox) { |
| 576 linux_sandbox->setuid_sandbox_client()->CloseDummyFile(); | 584 linux_sandbox->setuid_sandbox_client()->CloseDummyFile(); |
| 577 | 585 |
| 578 // Let the ZygoteHost know we're booting up. | 586 // Let the ZygoteHost know we're booting up. |
| 579 CHECK(UnixDomainSocket::SendMsg(kZygoteSocketPairFd, | 587 CHECK(UnixDomainSocket::SendMsg(kZygoteSocketPairFd, |
| 580 kZygoteBootMessage, | 588 kZygoteBootMessage, |
| 581 sizeof(kZygoteBootMessage), | 589 sizeof(kZygoteBootMessage), |
| 582 std::vector<int>())); | 590 std::vector<int>())); |
| 583 } | 591 } |
| 584 | 592 |
| 585 VLOG(1) << "ZygoteMain: initializing " << fork_delegates.size() | 593 VLOG(1) << "ZygoteMain: initializing " << fork_delegates.size() |
| 586 << " fork delegates"; | 594 << " fork delegates"; |
| 587 for (ScopedVector<ZygoteForkDelegate>::iterator i = fork_delegates.begin(); | 595 for (ScopedVector<ZygoteForkDelegate>::iterator i = fork_delegates.begin(); |
| 588 i != fork_delegates.end(); | 596 i != fork_delegates.end(); |
| 589 ++i) { | 597 ++i) { |
| 590 (*i)->Init(GetSandboxFD(), must_enable_setuid_sandbox); | 598 (*i)->Init(GetSandboxFD(), must_enable_setuid_sandbox); |
| 591 } | 599 } |
| 592 | 600 |
| 601 const std::vector<int> sandbox_fds_to_close_post_fork = |
| 602 linux_sandbox->GetFileDescriptorsToClose(); |
| 603 |
| 604 fds_to_close_post_fork.insert(fds_to_close_post_fork.end(), |
| 605 sandbox_fds_to_close_post_fork.begin(), |
| 606 sandbox_fds_to_close_post_fork.end()); |
| 607 base::Closure post_fork_parent_callback = |
| 608 base::Bind(&CloseFds, fds_to_close_post_fork); |
| 609 |
| 593 // Turn on the first layer of the sandbox if the configuration warrants it. | 610 // Turn on the first layer of the sandbox if the configuration warrants it. |
| 594 EnterLayerOneSandbox(linux_sandbox, must_enable_setuid_sandbox, | 611 EnterLayerOneSandbox(linux_sandbox, must_enable_setuid_sandbox, |
| 595 post_fork_parent_callback); | 612 &post_fork_parent_callback); |
| 596 | 613 |
| 614 // Extra children and file descriptors created that the Zygote must have |
| 615 // knowledge of. |
| 597 std::vector<pid_t> extra_children; | 616 std::vector<pid_t> extra_children; |
| 598 std::vector<int> extra_fds; | 617 std::vector<int> extra_fds; |
| 599 | 618 |
| 600 #if defined(ADDRESS_SANITIZER) | 619 #if defined(ADDRESS_SANITIZER) |
| 601 pid_t sancov_helper_pid = ForkSanitizerCoverageHelper( | 620 pid_t sancov_helper_pid = ForkSanitizerCoverageHelper( |
| 602 sancov_socket_fds[0], sancov_socket_fds[1], sancov_file_fd.Pass()); | 621 sancov_socket_fds[0], sancov_socket_fds[1], sancov_file_fd.Pass(), |
| 622 sandbox_fds_to_close_post_fork); |
| 603 // It's important that the zygote reaps the helper before dying. Otherwise, | 623 // It's important that the zygote reaps the helper before dying. Otherwise, |
| 604 // the destruction of the PID namespace could kill the helper before it | 624 // the destruction of the PID namespace could kill the helper before it |
| 605 // completes its I/O tasks. |sancov_helper_pid| will exit once the last | 625 // completes its I/O tasks. |sancov_helper_pid| will exit once the last |
| 606 // renderer holding the write end of |sancov_socket_fds| closes it. | 626 // renderer holding the write end of |sancov_socket_fds| closes it. |
| 607 extra_children.push_back(sancov_helper_pid); | 627 extra_children.push_back(sancov_helper_pid); |
| 608 // Sanitizer code in the renderers will inherit the write end of the socket | 628 // Sanitizer code in the renderers will inherit the write end of the socket |
| 609 // from the zygote. We must keep it open until the very end of the zygote's | 629 // from the zygote. We must keep it open until the very end of the zygote's |
| 610 // lifetime, even though we don't explicitly use it. | 630 // lifetime, even though we don't explicitly use it. |
| 611 extra_fds.push_back(sancov_socket_fds[1]); | 631 extra_fds.push_back(sancov_socket_fds[1]); |
| 612 #endif | 632 #endif |
| 613 | 633 |
| 614 int sandbox_flags = linux_sandbox->GetStatus(); | 634 int sandbox_flags = linux_sandbox->GetStatus(); |
| 615 bool setuid_sandbox_engaged = sandbox_flags & kSandboxLinuxSUID; | 635 bool setuid_sandbox_engaged = sandbox_flags & kSandboxLinuxSUID; |
| 616 CHECK_EQ(must_enable_setuid_sandbox, setuid_sandbox_engaged); | 636 CHECK_EQ(must_enable_setuid_sandbox, setuid_sandbox_engaged); |
| 617 | 637 |
| 618 Zygote zygote(sandbox_flags, fork_delegates.Pass(), extra_children, | 638 Zygote zygote(sandbox_flags, fork_delegates.Pass(), extra_children, |
| 619 extra_fds); | 639 extra_fds); |
| 620 // This function call can return multiple times, once per fork(). | 640 // This function call can return multiple times, once per fork(). |
| 621 return zygote.ProcessRequests(); | 641 return zygote.ProcessRequests(); |
| 622 } | 642 } |
| 623 | 643 |
| 624 } // namespace content | 644 } // namespace content |
| OLD | NEW |