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 <dlfcn.h> | 5 #include <dlfcn.h> |
6 #include <fcntl.h> | 6 #include <fcntl.h> |
7 #include <pthread.h> | 7 #include <pthread.h> |
8 #include <stdio.h> | 8 #include <stdio.h> |
9 #include <sys/socket.h> | 9 #include <sys/socket.h> |
10 #include <sys/stat.h> | 10 #include <sys/stat.h> |
(...skipping 13 matching lines...) Expand all Loading... |
24 #include "base/rand_util.h" | 24 #include "base/rand_util.h" |
25 #include "base/rand_util_c.h" | 25 #include "base/rand_util_c.h" |
26 #include "base/sys_info.h" | 26 #include "base/sys_info.h" |
27 #include "build/build_config.h" | 27 #include "build/build_config.h" |
28 #include "crypto/nss_util.h" | 28 #include "crypto/nss_util.h" |
29 #include "content/common/font_config_ipc_linux.h" | 29 #include "content/common/font_config_ipc_linux.h" |
30 #include "content/common/pepper_plugin_registry.h" | 30 #include "content/common/pepper_plugin_registry.h" |
31 #include "content/common/sandbox_methods_linux.h" | 31 #include "content/common/sandbox_methods_linux.h" |
32 #include "content/common/seccomp_sandbox.h" | 32 #include "content/common/seccomp_sandbox.h" |
33 #include "content/common/unix_domain_socket_posix.h" | 33 #include "content/common/unix_domain_socket_posix.h" |
| 34 #include "content/common/zygote_commands_linux.h" |
34 #include "content/public/common/content_switches.h" | 35 #include "content/public/common/content_switches.h" |
35 #include "content/public/common/main_function_params.h" | 36 #include "content/public/common/main_function_params.h" |
36 #include "content/public/common/sandbox_linux.h" | 37 #include "content/public/common/sandbox_linux.h" |
37 #include "content/public/common/zygote_fork_delegate_linux.h" | 38 #include "content/public/common/zygote_fork_delegate_linux.h" |
38 #include "content/zygote/zygote_linux.h" | 39 #include "content/zygote/zygote_linux.h" |
39 #include "skia/ext/SkFontHost_fontconfig_control.h" | 40 #include "skia/ext/SkFontHost_fontconfig_control.h" |
40 #include "unicode/timezone.h" | 41 #include "unicode/timezone.h" |
41 | 42 |
42 #if defined(OS_LINUX) | 43 #if defined(OS_LINUX) |
43 #include <sys/epoll.h> | 44 #include <sys/epoll.h> |
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 // It's possible that another hypothetical crypto stack would not require | 435 // It's possible that another hypothetical crypto stack would not require |
435 // pre-sandbox init, but more likely this is just a build configuration error. | 436 // pre-sandbox init, but more likely this is just a build configuration error. |
436 #error Which SSL library are you using? | 437 #error Which SSL library are you using? |
437 #endif | 438 #endif |
438 | 439 |
439 // Ensure access to the Pepper plugins before the sandbox is turned on. | 440 // Ensure access to the Pepper plugins before the sandbox is turned on. |
440 PepperPluginRegistry::PreloadModules(); | 441 PepperPluginRegistry::PreloadModules(); |
441 } | 442 } |
442 | 443 |
443 #if !defined(CHROMIUM_SELINUX) | 444 #if !defined(CHROMIUM_SELINUX) |
| 445 // Do nothing here |
| 446 static void SIGCHLDHandler(int signal) { |
| 447 } |
| 448 |
| 449 // The current process will become a process reaper like init. |
| 450 // We fork a child that will continue normally, when it dies, we can safely |
| 451 // exit. |
| 452 // We need to be careful we close the magic kZygoteIdFd properly in the parent |
| 453 // before this function returns. |
| 454 static bool CreateInitProcessReaper() { |
| 455 int sync_fds[2]; |
| 456 // We want to use send, so we can't use a pipe |
| 457 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sync_fds)) { |
| 458 LOG(ERROR) << "Failed to create socketpair"; |
| 459 return false; |
| 460 } |
| 461 |
| 462 // We use normal fork, not the ForkDelegate in this case since we are not a |
| 463 // true Zygote yet. |
| 464 pid_t child_pid = fork(); |
| 465 if (child_pid == -1) { |
| 466 (void) HANDLE_EINTR(close(sync_fds[0])); |
| 467 (void) HANDLE_EINTR(close(sync_fds[1])); |
| 468 return false; |
| 469 } |
| 470 if (child_pid) { |
| 471 // We are the parent, assuming the role of an init process. |
| 472 // The disposition for SIGCHLD cannot be SIG_IGN or wait() will only return |
| 473 // once all of our childs are dead. Since we're init we need to reap childs |
| 474 // as they come. |
| 475 struct sigaction action; |
| 476 memset(&action, 0, sizeof(action)); |
| 477 action.sa_handler = &SIGCHLDHandler; |
| 478 CHECK(sigaction(SIGCHLD, &action, NULL) == 0); |
| 479 |
| 480 (void) HANDLE_EINTR(close(sync_fds[0])); |
| 481 shutdown(sync_fds[1], SHUT_RD); |
| 482 // This "magic" socket must only appear in one process. |
| 483 (void) HANDLE_EINTR(close(content::kZygoteIdFd)); |
| 484 // Tell the child to continue |
| 485 CHECK(HANDLE_EINTR(send(sync_fds[1], "C", 1, MSG_NOSIGNAL)) == 1); |
| 486 |
| 487 for (;;) { |
| 488 // Loop until we have reaped our one natural child |
| 489 siginfo_t reaped_child_info; |
| 490 pid_t reaped_child = |
| 491 HANDLE_EINTR(waitid(P_ALL, 0, &reaped_child_info, WEXITED)); |
| 492 if (reaped_child == -1) |
| 493 _exit(1); |
| 494 if (reaped_child_info.si_pid == child_pid) { |
| 495 int exit_code = 0; |
| 496 // We're done waiting |
| 497 if (reaped_child_info.si_code == CLD_EXITED) { |
| 498 exit_code = reaped_child_info.si_status; |
| 499 } |
| 500 // Exit with the same exit code as our parent. This is most likely |
| 501 // useless. _exit with 0 if we got signaled. |
| 502 _exit(exit_code); |
| 503 } |
| 504 } |
| 505 } else { |
| 506 // The child needs to wait for the parent to close kZygoteIdFd to avoid a |
| 507 // race condition |
| 508 (void) HANDLE_EINTR(close(sync_fds[1])); |
| 509 shutdown(sync_fds[0], SHUT_WR); |
| 510 char should_continue; |
| 511 if (HANDLE_EINTR(read(sync_fds[0], &should_continue, 1)) == 1) |
| 512 return true; |
| 513 else |
| 514 return false; |
| 515 } |
| 516 } |
| 517 |
444 // This will set the *using_suid_sandbox variable to true if the SUID sandbox | 518 // This will set the *using_suid_sandbox variable to true if the SUID sandbox |
445 // is enabled. This does not necessarily exclude other types of sandboxing. | 519 // is enabled. This does not necessarily exclude other types of sandboxing. |
446 static bool EnterSandbox(bool* using_suid_sandbox) { | 520 static bool EnterSandbox(bool* using_suid_sandbox) { |
447 *using_suid_sandbox = false; | 521 *using_suid_sandbox = false; |
448 | 522 |
449 PreSandboxInit(); | 523 PreSandboxInit(); |
450 SkiaFontConfigSetImplementation( | 524 SkiaFontConfigSetImplementation( |
451 new FontConfigIPC(Zygote::kMagicSandboxIPCDescriptor)); | 525 new FontConfigIPC(Zygote::kMagicSandboxIPCDescriptor)); |
452 | 526 |
453 const char* const sandbox_fd_string = getenv(kSUIDSandboxVar); | 527 const char* const sandbox_fd_string = getenv(kSUIDSandboxVar); |
(...skipping 23 matching lines...) Expand all Loading... |
477 if (HANDLE_EINTR(read(fd, &reply, 1)) != 1) { | 551 if (HANDLE_EINTR(read(fd, &reply, 1)) != 1) { |
478 LOG(ERROR) << "Failed to read from chroot pipe: " << errno; | 552 LOG(ERROR) << "Failed to read from chroot pipe: " << errno; |
479 return false; | 553 return false; |
480 } | 554 } |
481 | 555 |
482 if (reply != kMsgChrootSuccessful) { | 556 if (reply != kMsgChrootSuccessful) { |
483 LOG(ERROR) << "Error code reply from chroot helper"; | 557 LOG(ERROR) << "Error code reply from chroot helper"; |
484 return false; | 558 return false; |
485 } | 559 } |
486 | 560 |
| 561 if (getpid() == 1) { |
| 562 // The setuid sandbox has created a new PID namespace and we need |
| 563 // to assume the role of init. |
| 564 if (!CreateInitProcessReaper()) { |
| 565 LOG(ERROR) << "Error creating an init process to reap zombies"; |
| 566 return false; |
| 567 } |
| 568 } |
| 569 |
487 #if !defined(OS_OPENBSD) | 570 #if !defined(OS_OPENBSD) |
488 // Previously, we required that the binary be non-readable. This causes the | 571 // Previously, we required that the binary be non-readable. This causes the |
489 // kernel to mark the process as non-dumpable at startup. The thinking was | 572 // kernel to mark the process as non-dumpable at startup. The thinking was |
490 // that, although we were putting the renderers into a PID namespace (with | 573 // that, although we were putting the renderers into a PID namespace (with |
491 // the SUID sandbox), they would nonetheless be in the /same/ PID | 574 // the SUID sandbox), they would nonetheless be in the /same/ PID |
492 // namespace. So they could ptrace each other unless they were non-dumpable. | 575 // namespace. So they could ptrace each other unless they were non-dumpable. |
493 // | 576 // |
494 // If the binary was readable, then there would be a window between process | 577 // If the binary was readable, then there would be a window between process |
495 // startup and the point where we set the non-dumpable flag in which a | 578 // startup and the point where we set the non-dumpable flag in which a |
496 // compromised renderer could ptrace attach. | 579 // compromised renderer could ptrace attach. |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
592 } | 675 } |
593 } | 676 } |
594 #endif // SECCOMP_SANDBOX | 677 #endif // SECCOMP_SANDBOX |
595 | 678 |
596 Zygote zygote(sandbox_flags, forkdelegate, proc_fd_for_seccomp); | 679 Zygote zygote(sandbox_flags, forkdelegate, proc_fd_for_seccomp); |
597 // This function call can return multiple times, once per fork(). | 680 // This function call can return multiple times, once per fork(). |
598 return zygote.ProcessRequests(); | 681 return zygote.ProcessRequests(); |
599 } | 682 } |
600 | 683 |
601 } // namespace content | 684 } // namespace content |
OLD | NEW |