| Index: content/common/sandbox_linux/sandbox_linux.cc
|
| diff --git a/content/common/sandbox_linux/sandbox_linux.cc b/content/common/sandbox_linux/sandbox_linux.cc
|
| index 12e11d8e1312d1480cbf7e7bb8bc27e9760ef156..5e66737ef6936a9360fc25b2e2d7f3e263fe5e57 100644
|
| --- a/content/common/sandbox_linux/sandbox_linux.cc
|
| +++ b/content/common/sandbox_linux/sandbox_linux.cc
|
| @@ -11,6 +11,8 @@
|
| #include <unistd.h>
|
|
|
| #include <limits>
|
| +#include <string>
|
| +#include <vector>
|
|
|
| #include "base/bind.h"
|
| #include "base/callback_helpers.h"
|
| @@ -90,10 +92,12 @@ int OpenProcTaskFd(int proc_fd) {
|
| if (proc_fd >= 0) {
|
| // If a handle to /proc is available, use it. This allows to bypass file
|
| // system restrictions.
|
| - proc_self_task = openat(proc_fd, "self/task/", O_RDONLY | O_DIRECTORY);
|
| + proc_self_task =
|
| + openat(proc_fd, "self/task/", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
|
| } else {
|
| // Otherwise, make an attempt to access the file system directly.
|
| - proc_self_task = open("/proc/self/task/", O_RDONLY | O_DIRECTORY);
|
| + proc_self_task =
|
| + open("/proc/self/task/", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
|
| }
|
| return proc_self_task;
|
| }
|
| @@ -109,6 +113,7 @@ LinuxSandbox::LinuxSandbox()
|
| pre_initialized_(false),
|
| seccomp_bpf_supported_(false),
|
| yama_is_enforcing_(false),
|
| + initialize_sandbox_ran_(false),
|
| setuid_sandbox_client_(sandbox::SetuidSandboxClient::Create())
|
| {
|
| if (setuid_sandbox_client_ == NULL) {
|
| @@ -121,6 +126,9 @@ LinuxSandbox::LinuxSandbox()
|
| }
|
|
|
| LinuxSandbox::~LinuxSandbox() {
|
| + if (pre_initialized_) {
|
| + CHECK(initialize_sandbox_ran_);
|
| + }
|
| }
|
|
|
| LinuxSandbox* LinuxSandbox::GetInstance() {
|
| @@ -144,12 +152,14 @@ void LinuxSandbox::PreinitializeSandbox() {
|
| // its contents before the sandbox is enabled. It also pre-opens the
|
| // object files that are already loaded in the process address space.
|
| base::debug::EnableInProcessStackDumpingForSandbox();
|
| +#endif // !defined(NDEBUG)
|
|
|
| - // Open proc_fd_ only in Debug mode so that forgetting to close it doesn't
|
| - // produce a sandbox escape in Release mode.
|
| + // Open proc_fd_. It would break the security of the setuid sandbox if it was
|
| + // not closed.
|
| + // If LinuxSandbox::PreinitializeSandbox() runs, InitializeSandbox() must run
|
| + // as well.
|
| proc_fd_ = open("/proc", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
|
| CHECK_GE(proc_fd_, 0);
|
| -#endif // !defined(NDEBUG)
|
| // We "pre-warm" the code that detects supports for seccomp BPF.
|
| if (SandboxSeccompBPF::IsSeccompBPFDesired()) {
|
| if (!SandboxSeccompBPF::SupportsSandbox()) {
|
| @@ -167,6 +177,10 @@ void LinuxSandbox::PreinitializeSandbox() {
|
| pre_initialized_ = true;
|
| }
|
|
|
| +std::vector<int> LinuxSandbox::GetFileDescriptorsToClose() {
|
| + return std::vector<int>{proc_fd_};
|
| +}
|
| +
|
| bool LinuxSandbox::InitializeSandbox() {
|
| LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance();
|
| return linux_sandbox->InitializeSandboxImpl();
|
| @@ -209,27 +223,14 @@ int LinuxSandbox::GetStatus() {
|
| // PID namespaces and existing sandboxes, so "self" must really be used instead
|
| // of using the pid.
|
| bool LinuxSandbox::IsSingleThreaded() const {
|
| - bool is_single_threaded = false;
|
| base::ScopedFD proc_self_task(OpenProcTaskFd(proc_fd_));
|
|
|
| -// In Debug mode, it's mandatory to be able to count threads to catch bugs.
|
| -#if !defined(NDEBUG)
|
| - // Using CHECK here since we want to check all the cases where
|
| - // !defined(NDEBUG)
|
| - // gets built.
|
| CHECK(proc_self_task.is_valid())
|
| << "Could not count threads, the sandbox was not "
|
| << "pre-initialized properly.";
|
| -#endif // !defined(NDEBUG)
|
|
|
| - if (!proc_self_task.is_valid()) {
|
| - // Pretend to be monothreaded if it can't be determined (for instance the
|
| - // setuid sandbox is already engaged but no proc_fd_ is available).
|
| - is_single_threaded = true;
|
| - } else {
|
| - is_single_threaded =
|
| - sandbox::ThreadHelpers::IsSingleThreaded(proc_self_task.get());
|
| - }
|
| + const bool is_single_threaded =
|
| + sandbox::ThreadHelpers::IsSingleThreaded(proc_self_task.get());
|
|
|
| return is_single_threaded;
|
| }
|
| @@ -247,16 +248,23 @@ sandbox::SetuidSandboxClient*
|
| bool LinuxSandbox::StartSeccompBPF(const std::string& process_type) {
|
| CHECK(!seccomp_bpf_started_);
|
| CHECK(pre_initialized_);
|
| - if (seccomp_bpf_supported())
|
| - seccomp_bpf_started_ = SandboxSeccompBPF::StartSandbox(process_type);
|
| + if (seccomp_bpf_supported()) {
|
| + base::ScopedFD proc_self_task(OpenProcTaskFd(proc_fd_));
|
| + seccomp_bpf_started_ =
|
| + SandboxSeccompBPF::StartSandbox(process_type, proc_self_task.Pass());
|
| + }
|
|
|
| - if (seccomp_bpf_started_)
|
| + if (seccomp_bpf_started_) {
|
| LogSandboxStarted("seccomp-bpf");
|
| + }
|
|
|
| return seccomp_bpf_started_;
|
| }
|
|
|
| bool LinuxSandbox::InitializeSandboxImpl() {
|
| + DCHECK(!initialize_sandbox_ran_);
|
| + initialize_sandbox_ran_ = true;
|
| +
|
| base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
| const std::string process_type =
|
| command_line->GetSwitchValueASCII(switches::kProcessType);
|
|
|