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 |