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_DGRAM, 0, sync_fds)) { | |
Markus (顧孟勤)
2012/05/21 23:57:00
On general principles, I would have used SOCK_STRE
jln (very slow on Chromium)
2012/05/22 00:36:43
I didn't know socketpair supported that. Thanks! I
| |
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 (void) HANDLE_EINTR(close(sync_fds[0])); | |
473 shutdown(sync_fds[1], SHUT_RD); | |
474 // This "magic" socket must only appear in one process. | |
475 (void) HANDLE_EINTR(close(content::kZygoteIdFd)); | |
476 // Tell the child to continue | |
477 int written = HANDLE_EINTR(send(sync_fds[1], "C", 1, MSG_NOSIGNAL)); | |
478 CHECK(written == 1); | |
Markus (顧孟勤)
2012/05/21 23:57:00
I typically prefer to put the actual function call
jln (very slow on Chromium)
2012/05/22 00:36:43
Done.
| |
479 | |
480 // The disposition for SIGCHLD cannot be SIG_IGN or wait() will only return | |
481 // once all of our childs are dead. Since we're init we need to reap childs | |
482 // as they come. | |
483 struct sigaction action; | |
484 memset(&action, 0, sizeof(action)); | |
485 action.sa_handler = &SIGCHLDHandler; | |
486 CHECK(sigaction(SIGCHLD, &action, NULL) == 0); | |
Markus (顧孟勤)
2012/05/21 23:57:00
You should set up the signal handler prior to writ
jln (very slow on Chromium)
2012/05/22 00:36:43
Done.
| |
487 | |
488 for (;;) { | |
489 // Loop until we have reaped our one natural child | |
490 pid_t reaped_child; | |
491 siginfo_t reaped_child_info; | |
492 int exit_code = 0; | |
Markus (顧孟勤)
2012/05/21 23:57:00
I'd probably move this variable into the block whe
jln (very slow on Chromium)
2012/05/22 00:36:43
Done.
| |
493 reaped_child = | |
Markus (顧孟勤)
2012/05/21 23:57:00
This is C++. You can define and use a variable on
jln (very slow on Chromium)
2012/05/22 00:36:43
Done.
| |
494 HANDLE_EINTR(waitid(P_ALL, 0, &reaped_child_info, WEXITED)); | |
495 if (reaped_child == -1) | |
496 _exit(1); | |
497 if (reaped_child_info.si_pid == child_pid) { | |
498 // We're done waiting | |
499 if (reaped_child_info.si_code == CLD_EXITED) { | |
500 exit_code = reaped_child_info.si_status; | |
501 } | |
502 // Exit with the same exit code as our parent. This is most likely | |
503 // useless. _exit with 0 if we got signaled. | |
504 _exit(exit_code); | |
505 } | |
506 } | |
507 } else { | |
508 // The child needs to wait for the parent to close kZygoteIdFd to avoid a | |
509 // race condition | |
510 (void) HANDLE_EINTR(close(sync_fds[1])); | |
511 shutdown(sync_fds[0], SHUT_WR); | |
512 char should_continue = '\0'; | |
513 (void) HANDLE_EINTR(read(sync_fds[0], &should_continue, 1)); | |
Markus (顧孟勤)
2012/05/21 23:57:00
I would have checked the return code of read(), bu
jln (very slow on Chromium)
2012/05/22 00:36:43
Done.
| |
514 if (should_continue != 'C') | |
515 return false; | |
516 else | |
517 return true; | |
518 } | |
519 } | |
520 | |
444 // This will set the *using_suid_sandbox variable to true if the SUID sandbox | 521 // 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. | 522 // is enabled. This does not necessarily exclude other types of sandboxing. |
446 static bool EnterSandbox(bool* using_suid_sandbox) { | 523 static bool EnterSandbox(bool* using_suid_sandbox) { |
447 *using_suid_sandbox = false; | 524 *using_suid_sandbox = false; |
448 | 525 |
449 PreSandboxInit(); | 526 PreSandboxInit(); |
450 SkiaFontConfigSetImplementation( | 527 SkiaFontConfigSetImplementation( |
451 new FontConfigIPC(Zygote::kMagicSandboxIPCDescriptor)); | 528 new FontConfigIPC(Zygote::kMagicSandboxIPCDescriptor)); |
452 | 529 |
453 const char* const sandbox_fd_string = getenv(kSUIDSandboxVar); | 530 const char* const sandbox_fd_string = getenv(kSUIDSandboxVar); |
(...skipping 23 matching lines...) Expand all Loading... | |
477 if (HANDLE_EINTR(read(fd, &reply, 1)) != 1) { | 554 if (HANDLE_EINTR(read(fd, &reply, 1)) != 1) { |
478 LOG(ERROR) << "Failed to read from chroot pipe: " << errno; | 555 LOG(ERROR) << "Failed to read from chroot pipe: " << errno; |
479 return false; | 556 return false; |
480 } | 557 } |
481 | 558 |
482 if (reply != kMsgChrootSuccessful) { | 559 if (reply != kMsgChrootSuccessful) { |
483 LOG(ERROR) << "Error code reply from chroot helper"; | 560 LOG(ERROR) << "Error code reply from chroot helper"; |
484 return false; | 561 return false; |
485 } | 562 } |
486 | 563 |
564 if (getpid() == 1) { | |
565 // The setuid sandbox has created a new PID namespace and we need | |
566 // to assume the role of init. | |
567 if (!CreateInitProcessReaper()) { | |
568 LOG(ERROR) << "Error creating an init process to reap zombies"; | |
569 return false; | |
570 } | |
571 } | |
572 | |
487 #if !defined(OS_OPENBSD) | 573 #if !defined(OS_OPENBSD) |
488 // Previously, we required that the binary be non-readable. This causes the | 574 // 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 | 575 // 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 | 576 // that, although we were putting the renderers into a PID namespace (with |
491 // the SUID sandbox), they would nonetheless be in the /same/ PID | 577 // the SUID sandbox), they would nonetheless be in the /same/ PID |
492 // namespace. So they could ptrace each other unless they were non-dumpable. | 578 // namespace. So they could ptrace each other unless they were non-dumpable. |
493 // | 579 // |
494 // If the binary was readable, then there would be a window between process | 580 // 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 | 581 // startup and the point where we set the non-dumpable flag in which a |
496 // compromised renderer could ptrace attach. | 582 // compromised renderer could ptrace attach. |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
592 } | 678 } |
593 } | 679 } |
594 #endif // SECCOMP_SANDBOX | 680 #endif // SECCOMP_SANDBOX |
595 | 681 |
596 Zygote zygote(sandbox_flags, forkdelegate, proc_fd_for_seccomp); | 682 Zygote zygote(sandbox_flags, forkdelegate, proc_fd_for_seccomp); |
597 // This function call can return multiple times, once per fork(). | 683 // This function call can return multiple times, once per fork(). |
598 return zygote.ProcessRequests(); | 684 return zygote.ProcessRequests(); |
599 } | 685 } |
600 | 686 |
601 } // namespace content | 687 } // namespace content |
OLD | NEW |