Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(382)

Side by Side Diff: content/zygote/zygote_main_linux.cc

Issue 733303004: Linux sandbox: change API to start the sandbox (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address nits from Jorge. Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/public/common/sandbox_init.h ('k') | sandbox/linux/BUILD.gn » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « content/public/common/sandbox_init.h ('k') | sandbox/linux/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698