| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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_communication_linux.h" | 5 #include "content/browser/zygote_host/zygote_communication_linux.h" |
| 6 | 6 |
| 7 #include <string.h> | 7 #include <string.h> |
| 8 #include <sys/socket.h> | 8 #include <sys/socket.h> |
| 9 | 9 |
| 10 #include "base/base_switches.h" | 10 #include "base/base_switches.h" |
| 11 #include "base/command_line.h" |
| 11 #include "base/logging.h" | 12 #include "base/logging.h" |
| 12 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
| 13 #include "base/metrics/sparse_histogram.h" | 14 #include "base/metrics/sparse_histogram.h" |
| 14 #include "base/path_service.h" | 15 #include "base/path_service.h" |
| 15 #include "base/pickle.h" | 16 #include "base/pickle.h" |
| 16 #include "base/posix/eintr_wrapper.h" | 17 #include "base/posix/eintr_wrapper.h" |
| 17 #include "base/posix/unix_domain_socket_linux.h" | 18 #include "base/posix/unix_domain_socket_linux.h" |
| 18 #include "content/browser/renderer_host/render_sandbox_host_linux.h" | 19 #include "content/browser/renderer_host/render_sandbox_host_linux.h" |
| 19 #include "content/browser/zygote_host/zygote_host_impl_linux.h" | 20 #include "content/browser/zygote_host/zygote_host_impl_linux.h" |
| 20 #include "content/common/child_process_sandbox_support_impl_linux.h" | 21 #include "content/common/child_process_sandbox_support_impl_linux.h" |
| 21 #include "content/common/zygote_commands_linux.h" | 22 #include "content/common/zygote_commands_linux.h" |
| 22 #include "content/public/browser/content_browser_client.h" | 23 #include "content/public/browser/content_browser_client.h" |
| 23 #include "content/public/common/content_switches.h" | 24 #include "content/public/common/content_switches.h" |
| 24 #include "content/public/common/result_codes.h" | 25 #include "content/public/common/result_codes.h" |
| 25 #include "sandbox/linux/services/credentials.h" | |
| 26 #include "sandbox/linux/services/namespace_sandbox.h" | 26 #include "sandbox/linux/services/namespace_sandbox.h" |
| 27 #include "sandbox/linux/suid/client/setuid_sandbox_host.h" | 27 #include "sandbox/linux/suid/client/setuid_sandbox_host.h" |
| 28 #include "ui/gfx/switches.h" | 28 #include "ui/gfx/switches.h" |
| 29 | 29 |
| 30 namespace content { | 30 namespace content { |
| 31 | 31 |
| 32 namespace { | 32 namespace { |
| 33 | 33 |
| 34 // Receive a fixed message on fd and return the sender's PID. | 34 // Receive a fixed message on fd and return the sender's PID. |
| 35 // Returns true if the message received matches the expected message. | 35 // Returns true if the message received matches the expected message. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 54 } // namespace | 54 } // namespace |
| 55 | 55 |
| 56 ZygoteCommunication::ZygoteCommunication() | 56 ZygoteCommunication::ZygoteCommunication() |
| 57 : control_fd_(-1), | 57 : control_fd_(-1), |
| 58 control_lock_(), | 58 control_lock_(), |
| 59 pid_(), | 59 pid_(), |
| 60 list_of_running_zygote_children_(), | 60 list_of_running_zygote_children_(), |
| 61 child_tracking_lock_(), | 61 child_tracking_lock_(), |
| 62 sandbox_status_(0), | 62 sandbox_status_(0), |
| 63 have_read_sandbox_status_word_(false), | 63 have_read_sandbox_status_word_(false), |
| 64 use_suid_sandbox_for_adj_oom_score_(false), | |
| 65 init_(false) {} | 64 init_(false) {} |
| 66 | 65 |
| 67 ZygoteCommunication::~ZygoteCommunication() {} | 66 ZygoteCommunication::~ZygoteCommunication() {} |
| 68 | 67 |
| 69 bool ZygoteCommunication::SendMessage(const base::Pickle& data, | 68 bool ZygoteCommunication::SendMessage(const base::Pickle& data, |
| 70 const std::vector<int>* fds) { | 69 const std::vector<int>* fds) { |
| 71 DCHECK_NE(-1, control_fd_); | 70 DCHECK_NE(-1, control_fd_); |
| 72 CHECK(data.size() <= kZygoteMaxMessageLength) | 71 CHECK(data.size() <= kZygoteMaxMessageLength) |
| 73 << "Trying to send too-large message to zygote (sending " << data.size() | 72 << "Trying to send too-large message to zygote (sending " << data.size() |
| 74 << " bytes, max is " << kZygoteMaxMessageLength << ")"; | 73 << " bytes, max is " << kZygoteMaxMessageLength << ")"; |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 // becomes a renderer process. | 287 // becomes a renderer process. |
| 289 switches::kForceDeviceScaleFactor, switches::kLoggingLevel, | 288 switches::kForceDeviceScaleFactor, switches::kLoggingLevel, |
| 290 switches::kNoSandbox, switches::kPpapiInProcess, | 289 switches::kNoSandbox, switches::kPpapiInProcess, |
| 291 switches::kRegisterPepperPlugins, switches::kV, switches::kVModule, | 290 switches::kRegisterPepperPlugins, switches::kV, switches::kVModule, |
| 292 }; | 291 }; |
| 293 cmd_line.CopySwitchesFrom(browser_command_line, kForwardSwitches, | 292 cmd_line.CopySwitchesFrom(browser_command_line, kForwardSwitches, |
| 294 arraysize(kForwardSwitches)); | 293 arraysize(kForwardSwitches)); |
| 295 | 294 |
| 296 GetContentClient()->browser()->AppendExtraCommandLineSwitches(&cmd_line, -1); | 295 GetContentClient()->browser()->AppendExtraCommandLineSwitches(&cmd_line, -1); |
| 297 | 296 |
| 298 const bool using_namespace_sandbox = ShouldUseNamespaceSandbox(); | 297 const bool using_namespace_sandbox = |
| 298 ZygoteHostImpl::GetInstance()->ShouldUseNamespaceSandbox(); |
| 299 // A non empty sandbox_cmd means we want a SUID sandbox. | 299 // A non empty sandbox_cmd means we want a SUID sandbox. |
| 300 const bool using_suid_sandbox = | 300 const bool using_suid_sandbox = |
| 301 !ZygoteHostImpl::GetInstance()->SandboxCommand().empty() && | 301 !ZygoteHostImpl::GetInstance()->SandboxCommand().empty() && |
| 302 !using_namespace_sandbox; | 302 !using_namespace_sandbox; |
| 303 // Use the SUID sandbox for adjusting OOM scores when we are using the setuid | |
| 304 // or namespace sandbox. This is needed beacuse the processes are | |
| 305 // non-dumpable, so /proc/pid/oom_score_adj can only be written by root. | |
| 306 use_suid_sandbox_for_adj_oom_score_ = using_suid_sandbox; | |
| 307 | |
| 308 #if defined(OS_CHROMEOS) | |
| 309 // Chrome OS has a kernel patch that restricts oom_score_adj. See | |
| 310 // crbug.com/576409 for details. | |
| 311 if (!ZygoteHostImpl::GetInstance()->SandboxCommand().empty() && | |
| 312 using_namespace_sandbox) { | |
| 313 use_suid_sandbox_for_adj_oom_score_ = true; | |
| 314 } | |
| 315 #endif | |
| 316 | 303 |
| 317 // Start up the sandbox host process and get the file descriptor for the | 304 // Start up the sandbox host process and get the file descriptor for the |
| 318 // renderers to talk to it. | 305 // renderers to talk to it. |
| 319 const int sfd = RenderSandboxHostLinux::GetInstance()->GetRendererSocket(); | 306 const int sfd = RenderSandboxHostLinux::GetInstance()->GetRendererSocket(); |
| 320 fds_to_map.push_back(std::make_pair(sfd, GetSandboxFD())); | 307 fds_to_map.push_back(std::make_pair(sfd, GetSandboxFD())); |
| 321 | 308 |
| 322 base::ScopedFD dummy_fd; | 309 base::ScopedFD dummy_fd; |
| 323 if (using_suid_sandbox) { | 310 if (using_suid_sandbox) { |
| 324 scoped_ptr<sandbox::SetuidSandboxHost> sandbox_host( | 311 scoped_ptr<sandbox::SetuidSandboxHost> sandbox_host( |
| 325 sandbox::SetuidSandboxHost::Create()); | 312 sandbox::SetuidSandboxHost::Create()); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 427 status = tmp_status; | 414 status = tmp_status; |
| 428 } | 415 } |
| 429 } | 416 } |
| 430 | 417 |
| 431 if (status != base::TERMINATION_STATUS_STILL_RUNNING) { | 418 if (status != base::TERMINATION_STATUS_STILL_RUNNING) { |
| 432 ZygoteChildDied(handle); | 419 ZygoteChildDied(handle); |
| 433 } | 420 } |
| 434 return static_cast<base::TerminationStatus>(status); | 421 return static_cast<base::TerminationStatus>(status); |
| 435 } | 422 } |
| 436 | 423 |
| 437 bool ZygoteCommunication::ShouldUseNamespaceSandbox() { | |
| 438 const base::CommandLine& command_line = | |
| 439 *base::CommandLine::ForCurrentProcess(); | |
| 440 if (command_line.HasSwitch(switches::kNoSandbox)) { | |
| 441 return false; | |
| 442 } | |
| 443 | |
| 444 if (command_line.HasSwitch(switches::kDisableNamespaceSandbox)) { | |
| 445 return false; | |
| 446 } | |
| 447 | |
| 448 if (!sandbox::Credentials::CanCreateProcessInNewUserNS()) { | |
| 449 return false; | |
| 450 } | |
| 451 | |
| 452 return true; | |
| 453 } | |
| 454 | |
| 455 int ZygoteCommunication::GetSandboxStatus() { | 424 int ZygoteCommunication::GetSandboxStatus() { |
| 456 if (have_read_sandbox_status_word_) { | 425 if (have_read_sandbox_status_word_) { |
| 457 return sandbox_status_; | 426 return sandbox_status_; |
| 458 } | 427 } |
| 459 if (ReadSandboxStatus() == -1) { | 428 if (ReadSandboxStatus() == -1) { |
| 460 return 0; | 429 return 0; |
| 461 } | 430 } |
| 462 have_read_sandbox_status_word_ = true; | 431 have_read_sandbox_status_word_ = true; |
| 463 UMA_HISTOGRAM_SPARSE_SLOWLY("Linux.SandboxStatus", sandbox_status_); | 432 UMA_HISTOGRAM_SPARSE_SLOWLY("Linux.SandboxStatus", sandbox_status_); |
| 464 return sandbox_status_; | 433 return sandbox_status_; |
| 465 } | 434 } |
| 466 | 435 |
| 467 } // namespace content | 436 } // namespace content |
| OLD | NEW |