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 <pthread.h> | 9 #include <pthread.h> |
9 #include <string.h> | 10 #include <string.h> |
11 #include <sys/socket.h> | |
10 #include <sys/types.h> | 12 #include <sys/types.h> |
11 #include <unistd.h> | 13 #include <unistd.h> |
12 | 14 |
13 #include "base/basictypes.h" | 15 #include "base/basictypes.h" |
14 #include "base/bind.h" | 16 #include "base/bind.h" |
15 #include "base/command_line.h" | 17 #include "base/command_line.h" |
16 #include "base/compiler_specific.h" | 18 #include "base/compiler_specific.h" |
17 #include "base/memory/scoped_vector.h" | 19 #include "base/memory/scoped_vector.h" |
18 #include "base/native_library.h" | 20 #include "base/native_library.h" |
19 #include "base/pickle.h" | 21 #include "base/pickle.h" |
22 #include "base/posix/eintr_wrapper.h" | |
20 #include "base/posix/unix_domain_socket_linux.h" | 23 #include "base/posix/unix_domain_socket_linux.h" |
21 #include "base/rand_util.h" | 24 #include "base/rand_util.h" |
22 #include "base/sys_info.h" | 25 #include "base/sys_info.h" |
23 #include "build/build_config.h" | 26 #include "build/build_config.h" |
24 #include "content/common/child_process_sandbox_support_impl_linux.h" | 27 #include "content/common/child_process_sandbox_support_impl_linux.h" |
25 #include "content/common/font_config_ipc_linux.h" | 28 #include "content/common/font_config_ipc_linux.h" |
26 #include "content/common/pepper_plugin_list.h" | 29 #include "content/common/pepper_plugin_list.h" |
27 #include "content/common/sandbox_linux/sandbox_linux.h" | 30 #include "content/common/sandbox_linux/sandbox_linux.h" |
28 #include "content/common/zygote_commands_linux.h" | 31 #include "content/common/zygote_commands_linux.h" |
29 #include "content/public/common/content_switches.h" | 32 #include "content/public/common/content_switches.h" |
(...skipping 10 matching lines...) Expand all Loading... | |
40 #include "third_party/skia/include/ports/SkFontConfigInterface.h" | 43 #include "third_party/skia/include/ports/SkFontConfigInterface.h" |
41 | 44 |
42 #if defined(OS_LINUX) | 45 #if defined(OS_LINUX) |
43 #include <sys/prctl.h> | 46 #include <sys/prctl.h> |
44 #endif | 47 #endif |
45 | 48 |
46 #if defined(ENABLE_WEBRTC) | 49 #if defined(ENABLE_WEBRTC) |
47 #include "third_party/libjingle/overrides/init_webrtc.h" | 50 #include "third_party/libjingle/overrides/init_webrtc.h" |
48 #endif | 51 #endif |
49 | 52 |
53 #if defined(ADDRESS_SANITIZER) | |
54 #include <sanitizer/asan_interface.h> | |
55 #endif | |
56 | |
50 namespace content { | 57 namespace content { |
51 | 58 |
52 // See http://code.google.com/p/chromium/wiki/LinuxZygote | 59 // See http://code.google.com/p/chromium/wiki/LinuxZygote |
53 | 60 |
54 static void ProxyLocaltimeCallToBrowser(time_t input, struct tm* output, | 61 static void ProxyLocaltimeCallToBrowser(time_t input, struct tm* output, |
55 char* timezone_out, | 62 char* timezone_out, |
56 size_t timezone_out_len) { | 63 size_t timezone_out_len) { |
57 Pickle request; | 64 Pickle request; |
58 request.WriteInt(LinuxSandbox::METHOD_LOCALTIME); | 65 request.WriteInt(LinuxSandbox::METHOD_LOCALTIME); |
59 request.WriteString( | 66 request.WriteString( |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
391 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) { | 398 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) { |
392 LOG(ERROR) << "Failed to set non-dumpable flag"; | 399 LOG(ERROR) << "Failed to set non-dumpable flag"; |
393 return false; | 400 return false; |
394 } | 401 } |
395 } | 402 } |
396 #endif | 403 #endif |
397 | 404 |
398 return true; | 405 return true; |
399 } | 406 } |
400 | 407 |
408 #if defined(ADDRESS_SANITIZER) | |
409 const size_t kSanitizerMaxMessageLength = 1 * 1024 * 1024; | |
410 | |
411 static void SanitizerCoverageHelper(int socket_fd, int file_fd) { | |
412 scoped_ptr<char[]> buffer(new char[kSanitizerMaxMessageLength]); | |
413 while (true) { | |
414 ssize_t received_size = HANDLE_EINTR( | |
415 recv(socket_fd, buffer.get(), kSanitizerMaxMessageLength, 0)); | |
jln (very slow on Chromium)
2014/05/21 01:07:37
Once the all renderers have exited and the Zygote
| |
416 PCHECK(received_size >= 0); | |
417 if (received_size > 0) { | |
418 PCHECK(file_fd >= 0); | |
419 ssize_t written_size = 0; | |
420 while (written_size < received_size) { | |
421 ssize_t write_res = | |
422 HANDLE_EINTR(write(file_fd, buffer.get() + written_size, | |
423 received_size - written_size)); | |
424 PCHECK(write_res >= 0); | |
425 written_size += write_res; | |
426 } | |
427 PCHECK(0 == HANDLE_EINTR(fsync(file_fd))); | |
428 } | |
429 } | |
430 } | |
431 | |
432 // fds[0] is the read end, fds[1] is the write end. | |
433 static void CreateSanitizerCoverageSocketPair(int fds[2]) { | |
jln (very slow on Chromium)
2014/05/21 01:07:37
How are you handling this socketpair on the *SAN s
| |
434 PCHECK(0 == socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds)); | |
435 PCHECK(0 == shutdown(fds[0], SHUT_WR)); | |
436 PCHECK(0 == shutdown(fds[1], SHUT_RD)); | |
437 } | |
438 | |
439 static void ForkSanitizerCoverageHelper(int child_fd, int parent_fd, | |
440 base::ScopedFD file_fd) { | |
441 pid_t pid = fork(); | |
442 PCHECK(pid >= 0); | |
443 if (pid == 0) { | |
444 // In the child. | |
445 PCHECK(0 == IGNORE_EINTR(close(parent_fd))); | |
446 SanitizerCoverageHelper(child_fd, file_fd.get()); | |
447 _exit(0); | |
448 } else { | |
449 // In the parent. | |
jln (very slow on Chromium)
2014/05/21 01:07:37
Could you add a note along the lines of:
- We wil
| |
450 PCHECK(0 == IGNORE_EINTR(close(child_fd))); | |
451 } | |
452 } | |
453 #endif | |
jln (very slow on Chromium)
2014/05/21 01:07:37
// defined(...)
| |
454 | |
401 // If |is_suid_sandbox_child|, then make sure that the setuid sandbox is | 455 // If |is_suid_sandbox_child|, then make sure that the setuid sandbox is |
402 // engaged. | 456 // engaged. |
403 static void EnterLayerOneSandbox(LinuxSandbox* linux_sandbox, | 457 static void EnterLayerOneSandbox(LinuxSandbox* linux_sandbox, |
404 bool is_suid_sandbox_child) { | 458 bool is_suid_sandbox_child) { |
405 DCHECK(linux_sandbox); | 459 DCHECK(linux_sandbox); |
406 | 460 |
407 ZygotePreSandboxInit(); | 461 ZygotePreSandboxInit(); |
408 | 462 |
409 // Check that the pre-sandbox initialization didn't spawn threads. | 463 // Check that the pre-sandbox initialization didn't spawn threads. |
410 #if !defined(THREAD_SANITIZER) | 464 #if !defined(THREAD_SANITIZER) |
411 DCHECK(linux_sandbox->IsSingleThreaded()); | 465 DCHECK(linux_sandbox->IsSingleThreaded()); |
412 #endif | 466 #endif |
413 | 467 |
414 sandbox::SetuidSandboxClient* setuid_sandbox = | 468 sandbox::SetuidSandboxClient* setuid_sandbox = |
415 linux_sandbox->setuid_sandbox_client(); | 469 linux_sandbox->setuid_sandbox_client(); |
416 | 470 |
417 if (is_suid_sandbox_child) { | 471 if (is_suid_sandbox_child) { |
418 CHECK(EnterSuidSandbox(setuid_sandbox)) << "Failed to enter setuid sandbox"; | 472 CHECK(EnterSuidSandbox(setuid_sandbox)) << "Failed to enter setuid sandbox"; |
419 } | 473 } |
420 } | 474 } |
421 | 475 |
422 bool ZygoteMain(const MainFunctionParams& params, | 476 bool ZygoteMain(const MainFunctionParams& params, |
423 ScopedVector<ZygoteForkDelegate> fork_delegates) { | 477 ScopedVector<ZygoteForkDelegate> fork_delegates) { |
424 g_am_zygote_or_renderer = true; | 478 g_am_zygote_or_renderer = true; |
425 sandbox::InitLibcUrandomOverrides(); | 479 sandbox::InitLibcUrandomOverrides(); |
426 | 480 |
427 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); | 481 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); |
482 | |
483 #if defined(ADDRESS_SANITIZER) | |
484 base::ScopedFD sancov_file_fd(__sanitizer_maybe_open_cov_file("zygote")); | |
485 int sancov_socket_fds[2] = {-1, -1}; | |
486 CreateSanitizerCoverageSocketPair(sancov_socket_fds); | |
487 linux_sandbox->sanitizer_args()->coverage_sandboxed = 1; | |
488 linux_sandbox->sanitizer_args()->coverage_fd = sancov_socket_fds[1]; | |
489 linux_sandbox->sanitizer_args()->coverage_max_block_size = | |
490 kSanitizerMaxMessageLength; | |
491 #endif | |
jln (very slow on Chromium)
2014/05/21 01:07:37
// defined(ADDRESS_SANITIZER)
| |
492 | |
428 // This will pre-initialize the various sandboxes that need it. | 493 // This will pre-initialize the various sandboxes that need it. |
429 linux_sandbox->PreinitializeSandbox(); | 494 linux_sandbox->PreinitializeSandbox(); |
430 | 495 |
431 const bool must_enable_setuid_sandbox = | 496 const bool must_enable_setuid_sandbox = |
432 linux_sandbox->setuid_sandbox_client()->IsSuidSandboxChild(); | 497 linux_sandbox->setuid_sandbox_client()->IsSuidSandboxChild(); |
433 if (must_enable_setuid_sandbox) { | 498 if (must_enable_setuid_sandbox) { |
434 linux_sandbox->setuid_sandbox_client()->CloseDummyFile(); | 499 linux_sandbox->setuid_sandbox_client()->CloseDummyFile(); |
435 | 500 |
436 // Let the ZygoteHost know we're booting up. | 501 // Let the ZygoteHost know we're booting up. |
437 CHECK(UnixDomainSocket::SendMsg(kZygoteSocketPairFd, | 502 CHECK(UnixDomainSocket::SendMsg(kZygoteSocketPairFd, |
438 kZygoteBootMessage, | 503 kZygoteBootMessage, |
439 sizeof(kZygoteBootMessage), | 504 sizeof(kZygoteBootMessage), |
440 std::vector<int>())); | 505 std::vector<int>())); |
441 } | 506 } |
442 | 507 |
443 VLOG(1) << "ZygoteMain: initializing " << fork_delegates.size() | 508 VLOG(1) << "ZygoteMain: initializing " << fork_delegates.size() |
444 << " fork delegates"; | 509 << " fork delegates"; |
445 for (ScopedVector<ZygoteForkDelegate>::iterator i = fork_delegates.begin(); | 510 for (ScopedVector<ZygoteForkDelegate>::iterator i = fork_delegates.begin(); |
446 i != fork_delegates.end(); | 511 i != fork_delegates.end(); |
447 ++i) { | 512 ++i) { |
448 (*i)->Init(GetSandboxFD(), must_enable_setuid_sandbox); | 513 (*i)->Init(GetSandboxFD(), must_enable_setuid_sandbox); |
449 } | 514 } |
450 | 515 |
451 // Turn on the first layer of the sandbox if the configuration warrants it. | 516 // Turn on the first layer of the sandbox if the configuration warrants it. |
452 EnterLayerOneSandbox(linux_sandbox, must_enable_setuid_sandbox); | 517 EnterLayerOneSandbox(linux_sandbox, must_enable_setuid_sandbox); |
453 | 518 |
519 #if defined(ADDRESS_SANITIZER) | |
520 ForkSanitizerCoverageHelper(sancov_socket_fds[0], sancov_socket_fds[1], | |
521 sancov_file_fd.Pass()); | |
522 #endif | |
523 | |
454 int sandbox_flags = linux_sandbox->GetStatus(); | 524 int sandbox_flags = linux_sandbox->GetStatus(); |
455 bool setuid_sandbox_engaged = sandbox_flags & kSandboxLinuxSUID; | 525 bool setuid_sandbox_engaged = sandbox_flags & kSandboxLinuxSUID; |
456 CHECK_EQ(must_enable_setuid_sandbox, setuid_sandbox_engaged); | 526 CHECK_EQ(must_enable_setuid_sandbox, setuid_sandbox_engaged); |
457 | 527 |
458 Zygote zygote(sandbox_flags, fork_delegates.Pass()); | 528 Zygote zygote(sandbox_flags, fork_delegates.Pass()); |
459 // This function call can return multiple times, once per fork(). | 529 // This function call can return multiple times, once per fork(). |
460 return zygote.ProcessRequests(); | 530 return zygote.ProcessRequests(); |
461 } | 531 } |
462 | 532 |
463 } // namespace content | 533 } // namespace content |
OLD | NEW |