| 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 <dirent.h> | 5 #include <dirent.h> |
| 6 #include <fcntl.h> | 6 #include <fcntl.h> |
| 7 #include <sys/resource.h> | 7 #include <sys/resource.h> |
| 8 #include <sys/stat.h> | 8 #include <sys/stat.h> |
| 9 #include <sys/time.h> | 9 #include <sys/time.h> |
| 10 #include <sys/types.h> | 10 #include <sys/types.h> |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 #include "base/posix/eintr_wrapper.h" | 21 #include "base/posix/eintr_wrapper.h" |
| 22 #include "base/strings/string_number_conversions.h" | 22 #include "base/strings/string_number_conversions.h" |
| 23 #include "base/time/time.h" | 23 #include "base/time/time.h" |
| 24 #include "build/build_config.h" | 24 #include "build/build_config.h" |
| 25 #include "content/common/sandbox_linux/sandbox_linux.h" | 25 #include "content/common/sandbox_linux/sandbox_linux.h" |
| 26 #include "content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h" | 26 #include "content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h" |
| 27 #include "content/public/common/content_switches.h" | 27 #include "content/public/common/content_switches.h" |
| 28 #include "content/public/common/sandbox_linux.h" | 28 #include "content/public/common/sandbox_linux.h" |
| 29 #include "sandbox/linux/services/credentials.h" | 29 #include "sandbox/linux/services/credentials.h" |
| 30 #include "sandbox/linux/services/thread_helpers.h" | 30 #include "sandbox/linux/services/thread_helpers.h" |
| 31 #include "sandbox/linux/services/yama.h" |
| 31 #include "sandbox/linux/suid/client/setuid_sandbox_client.h" | 32 #include "sandbox/linux/suid/client/setuid_sandbox_client.h" |
| 32 | 33 |
| 34 using sandbox::Yama; |
| 35 |
| 33 namespace { | 36 namespace { |
| 34 | 37 |
| 35 struct FDCloser { | 38 struct FDCloser { |
| 36 inline void operator()(int* fd) const { | 39 inline void operator()(int* fd) const { |
| 37 DCHECK(fd); | 40 DCHECK(fd); |
| 38 PCHECK(0 == IGNORE_EINTR(close(*fd))); | 41 PCHECK(0 == IGNORE_EINTR(close(*fd))); |
| 39 *fd = -1; | 42 *fd = -1; |
| 40 } | 43 } |
| 41 }; | 44 }; |
| 42 | 45 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 } // namespace | 100 } // namespace |
| 98 | 101 |
| 99 namespace content { | 102 namespace content { |
| 100 | 103 |
| 101 LinuxSandbox::LinuxSandbox() | 104 LinuxSandbox::LinuxSandbox() |
| 102 : proc_fd_(-1), | 105 : proc_fd_(-1), |
| 103 seccomp_bpf_started_(false), | 106 seccomp_bpf_started_(false), |
| 104 sandbox_status_flags_(kSandboxLinuxInvalid), | 107 sandbox_status_flags_(kSandboxLinuxInvalid), |
| 105 pre_initialized_(false), | 108 pre_initialized_(false), |
| 106 seccomp_bpf_supported_(false), | 109 seccomp_bpf_supported_(false), |
| 110 yama_is_enforcing_(false), |
| 107 setuid_sandbox_client_(sandbox::SetuidSandboxClient::Create()) { | 111 setuid_sandbox_client_(sandbox::SetuidSandboxClient::Create()) { |
| 108 if (setuid_sandbox_client_ == NULL) { | 112 if (setuid_sandbox_client_ == NULL) { |
| 109 LOG(FATAL) << "Failed to instantiate the setuid sandbox client."; | 113 LOG(FATAL) << "Failed to instantiate the setuid sandbox client."; |
| 110 } | 114 } |
| 111 } | 115 } |
| 112 | 116 |
| 113 LinuxSandbox::~LinuxSandbox() { | 117 LinuxSandbox::~LinuxSandbox() { |
| 114 } | 118 } |
| 115 | 119 |
| 116 LinuxSandbox* LinuxSandbox::GetInstance() { | 120 LinuxSandbox* LinuxSandbox::GetInstance() { |
| 117 LinuxSandbox* instance = Singleton<LinuxSandbox>::get(); | 121 LinuxSandbox* instance = Singleton<LinuxSandbox>::get(); |
| 118 CHECK(instance); | 122 CHECK(instance); |
| 119 return instance; | 123 return instance; |
| 120 } | 124 } |
| 121 | 125 |
| 122 #if defined(ADDRESS_SANITIZER) && defined(OS_LINUX) | 126 #if defined(ADDRESS_SANITIZER) && defined(OS_LINUX) |
| 123 // ASan API call to notify the tool the sandbox is going to be turned on. | 127 // ASan API call to notify the tool the sandbox is going to be turned on. |
| 124 extern "C" void __sanitizer_sandbox_on_notify(void *reserved); | 128 extern "C" void __sanitizer_sandbox_on_notify(void *reserved); |
| 125 #endif | 129 #endif |
| 126 | 130 |
| 127 void LinuxSandbox::PreinitializeSandbox() { | 131 void LinuxSandbox::PreinitializeSandbox() { |
| 128 CHECK(!pre_initialized_); | 132 CHECK(!pre_initialized_); |
| 129 seccomp_bpf_supported_ = false; | 133 seccomp_bpf_supported_ = false; |
| 130 #if defined(ADDRESS_SANITIZER) && defined(OS_LINUX) | 134 #if defined(ADDRESS_SANITIZER) && defined(OS_LINUX) |
| 131 // ASan needs to open some resources before the sandbox is enabled. | 135 // ASan needs to open some resources before the sandbox is enabled. |
| 132 // This should not fork, not launch threads, not open a directory. | 136 // This should not fork, not launch threads, not open a directory. |
| 133 __sanitizer_sandbox_on_notify(/*reserved*/NULL); | 137 __sanitizer_sandbox_on_notify(/*reserved*/ NULL); |
| 134 #endif | 138 #endif |
| 135 | 139 |
| 136 #if !defined(NDEBUG) | 140 #if !defined(NDEBUG) |
| 137 // Open proc_fd_ only in Debug mode so that forgetting to close it doesn't | 141 // Open proc_fd_ only in Debug mode so that forgetting to close it doesn't |
| 138 // produce a sandbox escape in Release mode. | 142 // produce a sandbox escape in Release mode. |
| 139 proc_fd_ = open("/proc", O_DIRECTORY | O_RDONLY); | 143 proc_fd_ = open("/proc", O_DIRECTORY | O_RDONLY); |
| 140 CHECK_GE(proc_fd_, 0); | 144 CHECK_GE(proc_fd_, 0); |
| 141 #endif // !defined(NDEBUG) | 145 #endif // !defined(NDEBUG) |
| 142 // We "pre-warm" the code that detects supports for seccomp BPF. | 146 // We "pre-warm" the code that detects supports for seccomp BPF. |
| 143 if (SandboxSeccompBPF::IsSeccompBPFDesired()) { | 147 if (SandboxSeccompBPF::IsSeccompBPFDesired()) { |
| 144 if (!SandboxSeccompBPF::SupportsSandbox()) { | 148 if (!SandboxSeccompBPF::SupportsSandbox()) { |
| 145 VLOG(1) << "Lacking support for seccomp-bpf sandbox."; | 149 VLOG(1) << "Lacking support for seccomp-bpf sandbox."; |
| 146 } else { | 150 } else { |
| 147 seccomp_bpf_supported_ = true; | 151 seccomp_bpf_supported_ = true; |
| 148 } | 152 } |
| 149 } | 153 } |
| 154 |
| 155 // Yama is a "global", system-level status. We assume it will not regress |
| 156 // after startup. |
| 157 const int yama_status = Yama::GetStatus(); |
| 158 yama_is_enforcing_ = (yama_status & Yama::STATUS_PRESENT) && |
| 159 (yama_status & Yama::STATUS_ENFORCING); |
| 150 pre_initialized_ = true; | 160 pre_initialized_ = true; |
| 151 } | 161 } |
| 152 | 162 |
| 153 bool LinuxSandbox::InitializeSandbox() { | 163 bool LinuxSandbox::InitializeSandbox() { |
| 154 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); | 164 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); |
| 155 return linux_sandbox->InitializeSandboxImpl(); | 165 return linux_sandbox->InitializeSandboxImpl(); |
| 156 } | 166 } |
| 157 | 167 |
| 158 void LinuxSandbox::StopThread(base::Thread* thread) { | 168 void LinuxSandbox::StopThread(base::Thread* thread) { |
| 159 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); | 169 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 172 if (setuid_sandbox_client_->IsInNewNETNamespace()) | 182 if (setuid_sandbox_client_->IsInNewNETNamespace()) |
| 173 sandbox_status_flags_ |= kSandboxLinuxNetNS; | 183 sandbox_status_flags_ |= kSandboxLinuxNetNS; |
| 174 } | 184 } |
| 175 | 185 |
| 176 // We report whether the sandbox will be activated when renderers, workers | 186 // We report whether the sandbox will be activated when renderers, workers |
| 177 // and PPAPI plugins go through sandbox initialization. | 187 // and PPAPI plugins go through sandbox initialization. |
| 178 if (seccomp_bpf_supported() && | 188 if (seccomp_bpf_supported() && |
| 179 SandboxSeccompBPF::ShouldEnableSeccompBPF(switches::kRendererProcess)) { | 189 SandboxSeccompBPF::ShouldEnableSeccompBPF(switches::kRendererProcess)) { |
| 180 sandbox_status_flags_ |= kSandboxLinuxSeccompBPF; | 190 sandbox_status_flags_ |= kSandboxLinuxSeccompBPF; |
| 181 } | 191 } |
| 192 |
| 193 if (yama_is_enforcing_) { |
| 194 sandbox_status_flags_ |= kSandboxLinuxYama; |
| 195 } |
| 182 } | 196 } |
| 183 | 197 |
| 184 return sandbox_status_flags_; | 198 return sandbox_status_flags_; |
| 185 } | 199 } |
| 186 | 200 |
| 187 // Threads are counted via /proc/self/task. This is a little hairy because of | 201 // Threads are counted via /proc/self/task. This is a little hairy because of |
| 188 // PID namespaces and existing sandboxes, so "self" must really be used instead | 202 // PID namespaces and existing sandboxes, so "self" must really be used instead |
| 189 // of using the pid. | 203 // of using the pid. |
| 190 bool LinuxSandbox::IsSingleThreaded() const { | 204 bool LinuxSandbox::IsSingleThreaded() const { |
| 191 bool is_single_threaded = false; | 205 bool is_single_threaded = false; |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 void LinuxSandbox::StopThreadAndEnsureNotCounted(base::Thread* thread) const { | 380 void LinuxSandbox::StopThreadAndEnsureNotCounted(base::Thread* thread) const { |
| 367 DCHECK(thread); | 381 DCHECK(thread); |
| 368 int proc_self_task = OpenProcTaskFd(proc_fd_); | 382 int proc_self_task = OpenProcTaskFd(proc_fd_); |
| 369 PCHECK(proc_self_task >= 0); | 383 PCHECK(proc_self_task >= 0); |
| 370 SafeScopedFD task_closer(&proc_self_task); | 384 SafeScopedFD task_closer(&proc_self_task); |
| 371 CHECK( | 385 CHECK( |
| 372 sandbox::ThreadHelpers::StopThreadAndWatchProcFS(proc_self_task, thread)); | 386 sandbox::ThreadHelpers::StopThreadAndWatchProcFS(proc_self_task, thread)); |
| 373 } | 387 } |
| 374 | 388 |
| 375 } // namespace content | 389 } // namespace content |
| OLD | NEW |