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

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

Issue 915823002: Namespace sandbox: add important security checks (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Better documentation. Created 5 years, 10 months 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
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>
(...skipping 13 matching lines...) Expand all
24 #include "base/pickle.h" 24 #include "base/pickle.h"
25 #include "base/posix/eintr_wrapper.h" 25 #include "base/posix/eintr_wrapper.h"
26 #include "base/posix/unix_domain_socket_linux.h" 26 #include "base/posix/unix_domain_socket_linux.h"
27 #include "base/rand_util.h" 27 #include "base/rand_util.h"
28 #include "base/strings/safe_sprintf.h" 28 #include "base/strings/safe_sprintf.h"
29 #include "base/strings/string_number_conversions.h" 29 #include "base/strings/string_number_conversions.h"
30 #include "base/sys_info.h" 30 #include "base/sys_info.h"
31 #include "build/build_config.h" 31 #include "build/build_config.h"
32 #include "content/common/child_process_sandbox_support_impl_linux.h" 32 #include "content/common/child_process_sandbox_support_impl_linux.h"
33 #include "content/common/font_config_ipc_linux.h" 33 #include "content/common/font_config_ipc_linux.h"
34 #include "content/common/sandbox_linux/sandbox_debug_handling_linux.h"
34 #include "content/common/sandbox_linux/sandbox_linux.h" 35 #include "content/common/sandbox_linux/sandbox_linux.h"
35 #include "content/common/zygote_commands_linux.h" 36 #include "content/common/zygote_commands_linux.h"
36 #include "content/public/common/content_switches.h" 37 #include "content/public/common/content_switches.h"
37 #include "content/public/common/main_function_params.h" 38 #include "content/public/common/main_function_params.h"
38 #include "content/public/common/sandbox_linux.h" 39 #include "content/public/common/sandbox_linux.h"
39 #include "content/public/common/zygote_fork_delegate_linux.h" 40 #include "content/public/common/zygote_fork_delegate_linux.h"
40 #include "content/zygote/zygote_linux.h" 41 #include "content/zygote/zygote_linux.h"
41 #include "crypto/nss_util.h" 42 #include "crypto/nss_util.h"
42 #include "sandbox/linux/services/credentials.h" 43 #include "sandbox/linux/services/credentials.h"
rickyz (no longer on Chrome) 2015/02/11 22:59:56 Can we get rid of this include in this case?
jln (very slow on Chromium) 2015/02/11 23:13:06 Done.
43 #include "sandbox/linux/services/init_process_reaper.h" 44 #include "sandbox/linux/services/init_process_reaper.h"
44 #include "sandbox/linux/services/libc_urandom_override.h" 45 #include "sandbox/linux/services/libc_urandom_override.h"
45 #include "sandbox/linux/services/namespace_sandbox.h" 46 #include "sandbox/linux/services/namespace_sandbox.h"
46 #include "sandbox/linux/suid/client/setuid_sandbox_client.h" 47 #include "sandbox/linux/suid/client/setuid_sandbox_client.h"
47 #include "third_party/icu/source/i18n/unicode/timezone.h" 48 #include "third_party/icu/source/i18n/unicode/timezone.h"
48 #include "third_party/skia/include/ports/SkFontConfigInterface.h" 49 #include "third_party/skia/include/ports/SkFontConfigInterface.h"
49 50
50 #if defined(OS_LINUX) 51 #if defined(OS_LINUX)
51 #include <sys/prctl.h> 52 #include <sys/prctl.h>
52 #endif 53 #endif
(...skipping 12 matching lines...) Expand all
65 #endif 66 #endif
66 67
67 #if defined(ADDRESS_SANITIZER) 68 #if defined(ADDRESS_SANITIZER)
68 #include <sanitizer/asan_interface.h> 69 #include <sanitizer/asan_interface.h>
69 #endif 70 #endif
70 71
71 namespace content { 72 namespace content {
72 73
73 namespace { 74 namespace {
74 75
75 void DoChrootSignalHandler(int) {
76 const int old_errno = errno;
77 const char kFirstMessage[] = "Chroot signal handler called.\n";
78 ignore_result(write(STDERR_FILENO, kFirstMessage, sizeof(kFirstMessage) - 1));
79
80 const int chroot_ret = chroot("/");
81
82 char kSecondMessage[100];
83 const ssize_t printed =
84 base::strings::SafeSPrintf(kSecondMessage,
85 "chroot() returned %d. Errno is %d.\n",
86 chroot_ret,
87 errno);
88 if (printed > 0 && printed < static_cast<ssize_t>(sizeof(kSecondMessage))) {
89 ignore_result(write(STDERR_FILENO, kSecondMessage, printed));
90 }
91 errno = old_errno;
92 }
93
94 // This is a quick hack to allow testing sandbox crash reports in production
95 // binaries.
96 // This installs a signal handler for SIGUSR2 that performs a chroot().
97 // In most of our BPF policies, it is a "watched" system call which will
98 // trigger a SIGSYS signal whose handler will crash.
99 // This has been added during the investigation of https://crbug.com/415842.
100 void InstallSandboxCrashTestHandler() {
101 struct sigaction act = {};
102 act.sa_handler = DoChrootSignalHandler;
103 CHECK_EQ(0, sigemptyset(&act.sa_mask));
104 act.sa_flags = 0;
105
106 PCHECK(0 == sigaction(SIGUSR2, &act, NULL));
107 }
108
109 void CloseFds(const std::vector<int>& fds) { 76 void CloseFds(const std::vector<int>& fds) {
110 for (const auto& it : fds) { 77 for (const auto& it : fds) {
111 PCHECK(0 == IGNORE_EINTR(close(it))); 78 PCHECK(0 == IGNORE_EINTR(close(it)));
112 } 79 }
113 } 80 }
114 81
115 } // namespace 82 } // namespace
116 83
117 // See http://code.google.com/p/chromium/wiki/LinuxZygote 84 // See http://code.google.com/p/chromium/wiki/LinuxZygote
118 85
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 // newly created process. 361 // newly created process.
395 const bool init_created = 362 const bool init_created =
396 sandbox::CreateInitProcessReaper(post_fork_parent_callback); 363 sandbox::CreateInitProcessReaper(post_fork_parent_callback);
397 if (!init_created) { 364 if (!init_created) {
398 LOG(ERROR) << "Error creating an init process to reap zombies"; 365 LOG(ERROR) << "Error creating an init process to reap zombies";
399 return false; 366 return false;
400 } 367 }
401 return true; 368 return true;
402 } 369 }
403 370
404 static bool MaybeSetProcessNonDumpable() {
405 const base::CommandLine& command_line =
406 *base::CommandLine::ForCurrentProcess();
407 if (command_line.HasSwitch(switches::kAllowSandboxDebugging)) {
408 // If sandbox debugging is allowed, install a handler for sandbox-related
409 // crash testing.
410 InstallSandboxCrashTestHandler();
411 return true;
412 }
413
414 if (prctl(PR_SET_DUMPABLE, 0) != 0) {
415 PLOG(ERROR) << "Failed to set non-dumpable flag";
416 return false;
417 }
418
419 return prctl(PR_GET_DUMPABLE) == 0;
420 }
421
422 // Enter the setuid sandbox. This requires the current process to have been 371 // Enter the setuid sandbox. This requires the current process to have been
423 // created through the setuid sandbox. 372 // created through the setuid sandbox.
424 static bool EnterSuidSandbox(sandbox::SetuidSandboxClient* setuid_sandbox, 373 static bool EnterSuidSandbox(sandbox::SetuidSandboxClient* setuid_sandbox,
425 base::Closure* post_fork_parent_callback) { 374 base::Closure* post_fork_parent_callback) {
426 DCHECK(setuid_sandbox); 375 DCHECK(setuid_sandbox);
427 DCHECK(setuid_sandbox->IsSuidSandboxChild()); 376 DCHECK(setuid_sandbox->IsSuidSandboxChild());
428 377
429 // Use the SUID sandbox. This still allows the seccomp sandbox to 378 // Use the SUID sandbox. This still allows the seccomp sandbox to
430 // be enabled by the process later. 379 // be enabled by the process later.
431 380
(...skipping 14 matching lines...) Expand all
446 "is not the init process. Please, make sure the SUID " 395 "is not the init process. Please, make sure the SUID "
447 "binary is up to date."; 396 "binary is up to date.";
448 } 397 }
449 398
450 if (getpid() == 1) { 399 if (getpid() == 1) {
451 // The setuid sandbox has created a new PID namespace and we need 400 // The setuid sandbox has created a new PID namespace and we need
452 // to assume the role of init. 401 // to assume the role of init.
453 CHECK(CreateInitProcessReaper(post_fork_parent_callback)); 402 CHECK(CreateInitProcessReaper(post_fork_parent_callback));
454 } 403 }
455 404
456 CHECK(MaybeSetProcessNonDumpable()); 405 CHECK(SandboxDebugHandling::SetDumpableStatusAndHandlers());
457 return true; 406 return true;
458 } 407 }
459 408
460 static void EnterNamespaceSandbox(base::Closure* post_fork_parent_callback) { 409 static void EnterNamespaceSandbox(LinuxSandbox* linux_sandbox,
461 pid_t pid = getpid(); 410 base::Closure* post_fork_parent_callback) {
462 if (sandbox::NamespaceSandbox::InNewPidNamespace()) { 411 linux_sandbox->EngageNamespaceSandbox();
463 CHECK_EQ(1, pid);
464 }
465 412
466 CHECK(sandbox::Credentials::MoveToNewUserNS()); 413 if (getpid() == 1) {
467 CHECK(sandbox::Credentials::DropFileSystemAccess());
468 CHECK(sandbox::Credentials::DropAllCapabilities());
469
470 // This needs to happen after moving to a new user NS, since doing so involves
471 // writing the UID/GID map.
472 CHECK(MaybeSetProcessNonDumpable());
473
474 if (pid == 1) {
475 CHECK(CreateInitProcessReaper(post_fork_parent_callback)); 414 CHECK(CreateInitProcessReaper(post_fork_parent_callback));
476 } 415 }
477 } 416 }
478 417
479 #if defined(ADDRESS_SANITIZER) 418 #if defined(ADDRESS_SANITIZER)
480 const size_t kSanitizerMaxMessageLength = 1 * 1024 * 1024; 419 const size_t kSanitizerMaxMessageLength = 1 * 1024 * 1024;
481 420
482 // A helper process which collects code coverage data from the renderers over a 421 // A helper process which collects code coverage data from the renderers over a
483 // socket and dumps it to a file. See http://crbug.com/336212 for discussion. 422 // socket and dumps it to a file. See http://crbug.com/336212 for discussion.
484 static void SanitizerCoverageHelper(int socket_fd, int file_fd) { 423 static void SanitizerCoverageHelper(int socket_fd, int file_fd) {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 #if !defined(THREAD_SANITIZER) 482 #if !defined(THREAD_SANITIZER)
544 DCHECK(linux_sandbox->IsSingleThreaded()); 483 DCHECK(linux_sandbox->IsSingleThreaded());
545 #endif 484 #endif
546 485
547 sandbox::SetuidSandboxClient* setuid_sandbox = 486 sandbox::SetuidSandboxClient* setuid_sandbox =
548 linux_sandbox->setuid_sandbox_client(); 487 linux_sandbox->setuid_sandbox_client();
549 if (setuid_sandbox->IsSuidSandboxChild()) { 488 if (setuid_sandbox->IsSuidSandboxChild()) {
550 CHECK(EnterSuidSandbox(setuid_sandbox, post_fork_parent_callback)) 489 CHECK(EnterSuidSandbox(setuid_sandbox, post_fork_parent_callback))
551 << "Failed to enter setuid sandbox"; 490 << "Failed to enter setuid sandbox";
552 } else if (sandbox::NamespaceSandbox::InNewUserNamespace()) { 491 } else if (sandbox::NamespaceSandbox::InNewUserNamespace()) {
553 EnterNamespaceSandbox(post_fork_parent_callback); 492 EnterNamespaceSandbox(linux_sandbox, post_fork_parent_callback);
554 } else { 493 } else {
555 CHECK(!using_layer1_sandbox); 494 CHECK(!using_layer1_sandbox);
556 } 495 }
557 } 496 }
558 497
559 bool ZygoteMain(const MainFunctionParams& params, 498 bool ZygoteMain(const MainFunctionParams& params,
560 ScopedVector<ZygoteForkDelegate> fork_delegates) { 499 ScopedVector<ZygoteForkDelegate> fork_delegates) {
561 g_am_zygote_or_renderer = true; 500 g_am_zygote_or_renderer = true;
562 sandbox::InitLibcUrandomOverrides(); 501 sandbox::InitLibcUrandomOverrides();
563 502
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
650 bool setuid_sandbox_engaged = sandbox_flags & kSandboxLinuxSUID; 589 bool setuid_sandbox_engaged = sandbox_flags & kSandboxLinuxSUID;
651 CHECK_EQ(using_setuid_sandbox, setuid_sandbox_engaged); 590 CHECK_EQ(using_setuid_sandbox, setuid_sandbox_engaged);
652 591
653 Zygote zygote(sandbox_flags, fork_delegates.Pass(), extra_children, 592 Zygote zygote(sandbox_flags, fork_delegates.Pass(), extra_children,
654 extra_fds); 593 extra_fds);
655 // This function call can return multiple times, once per fork(). 594 // This function call can return multiple times, once per fork().
656 return zygote.ProcessRequests(); 595 return zygote.ProcessRequests();
657 } 596 }
658 597
659 } // namespace content 598 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698