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

Side by Side Diff: content/browser/zygote_host/zygote_host_impl_linux.cc

Issue 897723005: Allow using the namespace sandbox in zygote host. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: More comments 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/browser/zygote_host/zygote_host_impl_linux.h" 5 #include "content/browser/zygote_host/zygote_host_impl_linux.h"
6 6
7 #include <string.h> 7 #include <string.h>
8 #include <sys/socket.h> 8 #include <sys/socket.h>
9 #include <sys/stat.h> 9 #include <sys/stat.h>
10 #include <sys/types.h> 10 #include <sys/types.h>
(...skipping 20 matching lines...) Expand all
31 #include "base/strings/string_number_conversions.h" 31 #include "base/strings/string_number_conversions.h"
32 #include "base/strings/string_util.h" 32 #include "base/strings/string_util.h"
33 #include "base/strings/utf_string_conversions.h" 33 #include "base/strings/utf_string_conversions.h"
34 #include "base/time/time.h" 34 #include "base/time/time.h"
35 #include "content/browser/renderer_host/render_sandbox_host_linux.h" 35 #include "content/browser/renderer_host/render_sandbox_host_linux.h"
36 #include "content/common/child_process_sandbox_support_impl_linux.h" 36 #include "content/common/child_process_sandbox_support_impl_linux.h"
37 #include "content/common/zygote_commands_linux.h" 37 #include "content/common/zygote_commands_linux.h"
38 #include "content/public/browser/content_browser_client.h" 38 #include "content/public/browser/content_browser_client.h"
39 #include "content/public/common/content_switches.h" 39 #include "content/public/common/content_switches.h"
40 #include "content/public/common/result_codes.h" 40 #include "content/public/common/result_codes.h"
41 #include "sandbox/linux/services/credentials.h"
42 #include "sandbox/linux/services/namespace_sandbox.h"
43 #include "sandbox/linux/services/namespace_utils.h"
41 #include "sandbox/linux/suid/client/setuid_sandbox_host.h" 44 #include "sandbox/linux/suid/client/setuid_sandbox_host.h"
42 #include "sandbox/linux/suid/common/sandbox.h" 45 #include "sandbox/linux/suid/common/sandbox.h"
43 #include "ui/base/ui_base_switches.h" 46 #include "ui/base/ui_base_switches.h"
44 #include "ui/gfx/switches.h" 47 #include "ui/gfx/switches.h"
45 48
46 #if defined(USE_TCMALLOC) 49 #if defined(USE_TCMALLOC)
47 #include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h" 50 #include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
48 #endif 51 #endif
49 52
50 namespace content { 53 namespace content {
51 54
55 namespace {
56
52 // Receive a fixed message on fd and return the sender's PID. 57 // Receive a fixed message on fd and return the sender's PID.
53 // Returns true if the message received matches the expected message. 58 // Returns true if the message received matches the expected message.
54 static bool ReceiveFixedMessage(int fd, 59 bool ReceiveFixedMessage(int fd,
55 const char* expect_msg, 60 const char* expect_msg,
56 size_t expect_len, 61 size_t expect_len,
57 base::ProcessId* sender_pid) { 62 base::ProcessId* sender_pid) {
58 char buf[expect_len + 1]; 63 char buf[expect_len + 1];
59 ScopedVector<base::ScopedFD> fds_vec; 64 ScopedVector<base::ScopedFD> fds_vec;
60 65
61 const ssize_t len = UnixDomainSocket::RecvMsgWithPid( 66 const ssize_t len = UnixDomainSocket::RecvMsgWithPid(
62 fd, buf, sizeof(buf), &fds_vec, sender_pid); 67 fd, buf, sizeof(buf), &fds_vec, sender_pid);
63 if (static_cast<size_t>(len) != expect_len) 68 if (static_cast<size_t>(len) != expect_len)
64 return false; 69 return false;
65 if (memcmp(buf, expect_msg, expect_len) != 0) 70 if (memcmp(buf, expect_msg, expect_len) != 0)
66 return false; 71 return false;
67 if (!fds_vec.empty()) 72 if (!fds_vec.empty())
68 return false; 73 return false;
69 return true; 74 return true;
70 } 75 }
71 76
77 } // namespace
78
72 // static 79 // static
73 ZygoteHost* ZygoteHost::GetInstance() { 80 ZygoteHost* ZygoteHost::GetInstance() {
74 return ZygoteHostImpl::GetInstance(); 81 return ZygoteHostImpl::GetInstance();
75 } 82 }
76 83
77 ZygoteHostImpl::ZygoteHostImpl() 84 ZygoteHostImpl::ZygoteHostImpl()
78 : control_fd_(-1), 85 : control_fd_(-1),
79 control_lock_(), 86 control_lock_(),
80 pid_(-1), 87 pid_(-1),
81 init_(false), 88 init_(false),
82 using_suid_sandbox_(false), 89 use_suid_sandbox_for_adj_oom_score_(false),
83 sandbox_binary_(), 90 sandbox_binary_(),
84 have_read_sandbox_status_word_(false), 91 have_read_sandbox_status_word_(false),
85 sandbox_status_(0), 92 sandbox_status_(0),
86 child_tracking_lock_(), 93 child_tracking_lock_(),
87 list_of_running_zygote_children_(), 94 list_of_running_zygote_children_(),
88 should_teardown_after_last_child_exits_(false) {} 95 should_teardown_after_last_child_exits_(false) {}
89 96
90 ZygoteHostImpl::~ZygoteHostImpl() { TearDown(); } 97 ZygoteHostImpl::~ZygoteHostImpl() { TearDown(); }
91 98
92 // static 99 // static
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 switches::kV, 141 switches::kV,
135 switches::kVModule, 142 switches::kVModule,
136 }; 143 };
137 cmd_line.CopySwitchesFrom(browser_command_line, kForwardSwitches, 144 cmd_line.CopySwitchesFrom(browser_command_line, kForwardSwitches,
138 arraysize(kForwardSwitches)); 145 arraysize(kForwardSwitches));
139 146
140 GetContentClient()->browser()->AppendExtraCommandLineSwitches(&cmd_line, -1); 147 GetContentClient()->browser()->AppendExtraCommandLineSwitches(&cmd_line, -1);
141 148
142 sandbox_binary_ = sandbox_cmd.c_str(); 149 sandbox_binary_ = sandbox_cmd.c_str();
143 150
151 const bool using_namespace_sandbox = ShouldUseNamespaceSandbox();
144 // A non empty sandbox_cmd means we want a SUID sandbox. 152 // A non empty sandbox_cmd means we want a SUID sandbox.
145 using_suid_sandbox_ = !sandbox_cmd.empty(); 153 const bool using_suid_sandbox =
154 !sandbox_cmd.empty() && !using_namespace_sandbox;
155
156 // Use the SUID sandbox for adjusting OOM scores when we are using the setuid
157 // or namespace sandbox. This is needed beacuse the processes are
158 // non-dumpable, so /proc/pid/oom_score_adj can only be written by root.
159 use_suid_sandbox_for_adj_oom_score_ =
160 using_namespace_sandbox || using_suid_sandbox;
146 161
147 // Start up the sandbox host process and get the file descriptor for the 162 // Start up the sandbox host process and get the file descriptor for the
148 // renderers to talk to it. 163 // renderers to talk to it.
149 const int sfd = RenderSandboxHostLinux::GetInstance()->GetRendererSocket(); 164 const int sfd = RenderSandboxHostLinux::GetInstance()->GetRendererSocket();
150 fds_to_map.push_back(std::make_pair(sfd, GetSandboxFD())); 165 fds_to_map.push_back(std::make_pair(sfd, GetSandboxFD()));
151 166
152 base::ScopedFD dummy_fd; 167 base::ScopedFD dummy_fd;
153 if (using_suid_sandbox_) { 168 if (using_suid_sandbox) {
154 scoped_ptr<sandbox::SetuidSandboxHost> sandbox_host( 169 scoped_ptr<sandbox::SetuidSandboxHost> sandbox_host(
155 sandbox::SetuidSandboxHost::Create()); 170 sandbox::SetuidSandboxHost::Create());
156 sandbox_host->PrependWrapper(&cmd_line); 171 sandbox_host->PrependWrapper(&cmd_line);
157 sandbox_host->SetupLaunchOptions(&options, &fds_to_map, &dummy_fd); 172 sandbox_host->SetupLaunchOptions(&options, &fds_to_map, &dummy_fd);
158 sandbox_host->SetupLaunchEnvironment(); 173 sandbox_host->SetupLaunchEnvironment();
159 } 174 }
160 175
161 options.fds_to_remap = &fds_to_map; 176 options.fds_to_remap = &fds_to_map;
162 base::Process process = base::LaunchProcess(cmd_line.argv(), options); 177 base::Process process =
178 using_namespace_sandbox
179 ? sandbox::NamespaceSandbox::LaunchProcess(cmd_line, options)
180 : base::LaunchProcess(cmd_line, options);
163 CHECK(process.IsValid()) << "Failed to launch zygote process"; 181 CHECK(process.IsValid()) << "Failed to launch zygote process";
182
164 dummy_fd.reset(); 183 dummy_fd.reset();
165 184
166 if (using_suid_sandbox_) { 185 if (using_suid_sandbox) {
167 // The SUID sandbox will execute the zygote in a new PID namespace, and 186 // The SUID sandbox will execute the zygote in a new PID namespace, and
168 // the main zygote process will then fork from there. Watch now our 187 // the main zygote process will then fork from there. Watch now our
169 // elaborate dance to find and validate the zygote's PID. 188 // elaborate dance to find and validate the zygote's PID.
170 189
171 // First we receive a message from the zygote boot process. 190 // First we receive a message from the zygote boot process.
172 base::ProcessId boot_pid; 191 base::ProcessId boot_pid;
173 CHECK(ReceiveFixedMessage( 192 CHECK(ReceiveFixedMessage(
174 fds[0], kZygoteBootMessage, sizeof(kZygoteBootMessage), &boot_pid)); 193 fds[0], kZygoteBootMessage, sizeof(kZygoteBootMessage), &boot_pid));
175 194
176 // Within the PID namespace, the zygote boot process thinks it's PID 1, 195 // Within the PID namespace, the zygote boot process thinks it's PID 1,
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
451 if (!selinux_valid) { 470 if (!selinux_valid) {
452 const base::FilePath kSelinuxPath("/selinux"); 471 const base::FilePath kSelinuxPath("/selinux");
453 base::FileEnumerator en(kSelinuxPath, false, base::FileEnumerator::FILES); 472 base::FileEnumerator en(kSelinuxPath, false, base::FileEnumerator::FILES);
454 bool has_selinux_files = !en.Next().empty(); 473 bool has_selinux_files = !en.Next().empty();
455 474
456 selinux = access(kSelinuxPath.value().c_str(), X_OK) == 0 && 475 selinux = access(kSelinuxPath.value().c_str(), X_OK) == 0 &&
457 has_selinux_files; 476 has_selinux_files;
458 selinux_valid = true; 477 selinux_valid = true;
459 } 478 }
460 479
461 if (using_suid_sandbox_ && !selinux) { 480 if (use_suid_sandbox_for_adj_oom_score_ && !selinux) {
462 #if defined(USE_TCMALLOC) 481 #if defined(USE_TCMALLOC)
463 // If heap profiling is running, these processes are not exiting, at least 482 // If heap profiling is running, these processes are not exiting, at least
464 // on ChromeOS. The easiest thing to do is not launch them when profiling. 483 // on ChromeOS. The easiest thing to do is not launch them when profiling.
465 // TODO(stevenjb): Investigate further and fix. 484 // TODO(stevenjb): Investigate further and fix.
466 if (IsHeapProfilerRunning()) 485 if (IsHeapProfilerRunning())
467 return; 486 return;
468 #endif 487 #endif
469 std::vector<std::string> adj_oom_score_cmdline; 488 std::vector<std::string> adj_oom_score_cmdline;
470 adj_oom_score_cmdline.push_back(sandbox_binary_); 489 adj_oom_score_cmdline.push_back(sandbox_binary_);
471 adj_oom_score_cmdline.push_back(sandbox::kAdjustOOMScoreSwitch); 490 adj_oom_score_cmdline.push_back(sandbox::kAdjustOOMScoreSwitch);
472 adj_oom_score_cmdline.push_back(base::Int64ToString(pid)); 491 adj_oom_score_cmdline.push_back(base::Int64ToString(pid));
473 adj_oom_score_cmdline.push_back(base::IntToString(score)); 492 adj_oom_score_cmdline.push_back(base::IntToString(score));
474 493
475 base::Process sandbox_helper_process; 494 base::Process sandbox_helper_process;
476 base::LaunchOptions options; 495 base::LaunchOptions options;
477 496
478 // sandbox_helper_process is a setuid binary. 497 // sandbox_helper_process is a setuid binary.
479 options.allow_new_privs = true; 498 options.allow_new_privs = true;
480 499
481 sandbox_helper_process = 500 sandbox_helper_process =
482 base::LaunchProcess(adj_oom_score_cmdline, options); 501 base::LaunchProcess(adj_oom_score_cmdline, options);
483 if (sandbox_helper_process.IsValid()) 502 if (sandbox_helper_process.IsValid())
484 base::EnsureProcessGetsReaped(sandbox_helper_process.Pid()); 503 base::EnsureProcessGetsReaped(sandbox_helper_process.Pid());
485 } else if (!using_suid_sandbox_) { 504 } else if (!use_suid_sandbox_for_adj_oom_score_) {
486 if (!base::AdjustOOMScore(pid, score)) 505 if (!base::AdjustOOMScore(pid, score))
487 PLOG(ERROR) << "Failed to adjust OOM score of renderer with pid " << pid; 506 PLOG(ERROR) << "Failed to adjust OOM score of renderer with pid " << pid;
488 } 507 }
489 } 508 }
490 #endif 509 #endif
491 510
492 void ZygoteHostImpl::EnsureProcessTerminated(pid_t process) { 511 void ZygoteHostImpl::EnsureProcessTerminated(pid_t process) {
493 DCHECK(init_); 512 DCHECK(init_);
494 Pickle pickle; 513 Pickle pickle;
495 514
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 pid_t ZygoteHostImpl::GetPid() const { 571 pid_t ZygoteHostImpl::GetPid() const {
553 return pid_; 572 return pid_;
554 } 573 }
555 574
556 int ZygoteHostImpl::GetSandboxStatus() const { 575 int ZygoteHostImpl::GetSandboxStatus() const {
557 if (have_read_sandbox_status_word_) 576 if (have_read_sandbox_status_word_)
558 return sandbox_status_; 577 return sandbox_status_;
559 return 0; 578 return 0;
560 } 579 }
561 580
581 bool ZygoteHostImpl::ShouldUseNamespaceSandbox() {
582 const base::CommandLine& command_line =
583 *base::CommandLine::ForCurrentProcess();
584 if (command_line.HasSwitch(switches::kNoSandbox)) {
585 return false;
586 }
587
588 if (!command_line.HasSwitch(switches::kEnableNamespaceSandbox)) {
589 return false;
590 }
591
592 if (!sandbox::Credentials::CanCreateProcessInNewUserNS()) {
593 return false;
594 }
595
596 return true;
597 }
598
562 } // namespace content 599 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/zygote_host/zygote_host_impl_linux.h ('k') | content/public/common/content_switches.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698