| 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 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 } | 72 } |
| 73 | 73 |
| 74 bool IsRunningTSAN() { | 74 bool IsRunningTSAN() { |
| 75 #if defined(THREAD_SANITIZER) | 75 #if defined(THREAD_SANITIZER) |
| 76 return true; | 76 return true; |
| 77 #else | 77 #else |
| 78 return false; | 78 return false; |
| 79 #endif | 79 #endif |
| 80 } | 80 } |
| 81 | 81 |
| 82 bool IsChromeOS() { | |
| 83 #if defined(OS_CHROMEOS) | |
| 84 return true; | |
| 85 #else | |
| 86 return false; | |
| 87 #endif | |
| 88 } | |
| 89 | |
| 90 // Try to open /proc/self/task/ with the help of |proc_fd|. |proc_fd| can be | 82 // Try to open /proc/self/task/ with the help of |proc_fd|. |proc_fd| can be |
| 91 // -1. Will return -1 on error and set errno like open(2). | 83 // -1. Will return -1 on error and set errno like open(2). |
| 92 int OpenProcTaskFd(int proc_fd) { | 84 int OpenProcTaskFd(int proc_fd) { |
| 93 int proc_self_task = -1; | 85 int proc_self_task = -1; |
| 94 if (proc_fd >= 0) { | 86 if (proc_fd >= 0) { |
| 95 // If a handle to /proc is available, use it. This allows to bypass file | 87 // If a handle to /proc is available, use it. This allows to bypass file |
| 96 // system restrictions. | 88 // system restrictions. |
| 97 proc_self_task = openat(proc_fd, "self/task/", O_RDONLY | O_DIRECTORY); | 89 proc_self_task = openat(proc_fd, "self/task/", O_RDONLY | O_DIRECTORY); |
| 98 } else { | 90 } else { |
| 99 // Otherwise, make an attempt to access the file system directly. | 91 // Otherwise, make an attempt to access the file system directly. |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 if (seccomp_bpf_supported()) | 229 if (seccomp_bpf_supported()) |
| 238 seccomp_bpf_started_ = SandboxSeccompBPF::StartSandbox(process_type); | 230 seccomp_bpf_started_ = SandboxSeccompBPF::StartSandbox(process_type); |
| 239 | 231 |
| 240 if (seccomp_bpf_started_) | 232 if (seccomp_bpf_started_) |
| 241 LogSandboxStarted("seccomp-bpf"); | 233 LogSandboxStarted("seccomp-bpf"); |
| 242 | 234 |
| 243 return seccomp_bpf_started_; | 235 return seccomp_bpf_started_; |
| 244 } | 236 } |
| 245 | 237 |
| 246 bool LinuxSandbox::InitializeSandboxImpl() { | 238 bool LinuxSandbox::InitializeSandboxImpl() { |
| 247 CommandLine* command_line = CommandLine::ForCurrentProcess(); | |
| 248 const std::string process_type = | 239 const std::string process_type = |
| 249 command_line->GetSwitchValueASCII(switches::kProcessType); | 240 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| 241 switches::kProcessType); |
| 250 | 242 |
| 251 // We need to make absolutely sure that our sandbox is "sealed" before | 243 // We need to make absolutely sure that our sandbox is "sealed" before |
| 252 // returning. | 244 // returning. |
| 253 // Unretained() since the current object is a Singleton. | 245 // Unretained() since the current object is a Singleton. |
| 254 base::ScopedClosureRunner sandbox_sealer( | 246 base::ScopedClosureRunner sandbox_sealer( |
| 255 base::Bind(&LinuxSandbox::SealSandbox, base::Unretained(this))); | 247 base::Bind(&LinuxSandbox::SealSandbox, base::Unretained(this))); |
| 256 // Make sure that this function enables sandboxes as promised by GetStatus(). | 248 // Make sure that this function enables sandboxes as promised by GetStatus(). |
| 257 // Unretained() since the current object is a Singleton. | 249 // Unretained() since the current object is a Singleton. |
| 258 base::ScopedClosureRunner sandbox_promise_keeper( | 250 base::ScopedClosureRunner sandbox_promise_keeper( |
| 259 base::Bind(&LinuxSandbox::CheckForBrokenPromises, | 251 base::Bind(&LinuxSandbox::CheckForBrokenPromises, |
| 260 base::Unretained(this), | 252 base::Unretained(this), |
| 261 process_type)); | 253 process_type)); |
| 262 | 254 |
| 263 // No matter what, it's always an error to call InitializeSandbox() after | 255 // No matter what, it's always an error to call InitializeSandbox() after |
| 264 // threads have been created. | 256 // threads have been created. |
| 265 if (!IsSingleThreaded()) { | 257 if (!IsSingleThreaded()) { |
| 266 std::string error_message = "InitializeSandbox() called with multiple " | 258 std::string error_message = "InitializeSandbox() called with multiple " |
| 267 "threads in process " + process_type; | 259 "threads in process " + process_type; |
| 268 // TSAN starts a helper thread. So we don't start the sandbox and don't | 260 // TSAN starts a helper thread. So we don't start the sandbox and don't |
| 269 // even report an error about it. | 261 // even report an error about it. |
| 270 if (IsRunningTSAN()) | 262 if (IsRunningTSAN()) |
| 271 return false; | 263 return false; |
| 272 | 264 // The GPU process is allowed to call InitializeSandbox() with threads for |
| 273 // The GPU process is allowed to call InitializeSandbox() with threads. | 265 // now, because it loads third-party libraries. |
| 274 bool sandbox_failure_fatal = process_type != switches::kGpuProcess; | 266 if (process_type != switches::kGpuProcess) |
| 275 | 267 CHECK(false) << error_message; |
| 276 // On Chrome OS, the GPU process is only allowed to call InitializeSandbox() | |
| 277 // with threads if '--gpu-sandbox-failures-nonfatal' is passed. | |
| 278 if (IsChromeOS()) { | |
| 279 sandbox_failure_fatal |= | |
| 280 !command_line->HasSwitch(switches::kGpuSandboxFailuresNonfatal); | |
| 281 } | |
| 282 | |
| 283 if (sandbox_failure_fatal) | |
| 284 LOG(FATAL) << error_message; | |
| 285 | |
| 286 LOG(ERROR) << error_message; | 268 LOG(ERROR) << error_message; |
| 287 return false; | 269 return false; |
| 288 } | 270 } |
| 289 | 271 |
| 290 // Only one thread is running, pre-initialize if not already done. | 272 // Only one thread is running, pre-initialize if not already done. |
| 291 if (!pre_initialized_) | 273 if (!pre_initialized_) |
| 292 PreinitializeSandbox(); | 274 PreinitializeSandbox(); |
| 293 | 275 |
| 294 DCHECK(!HasOpenDirectories()) << | 276 DCHECK(!HasOpenDirectories()) << |
| 295 "InitializeSandbox() called after unexpected directories have been " << | 277 "InitializeSandbox() called after unexpected directories have been " << |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 void LinuxSandbox::StopThreadAndEnsureNotCounted(base::Thread* thread) const { | 366 void LinuxSandbox::StopThreadAndEnsureNotCounted(base::Thread* thread) const { |
| 385 DCHECK(thread); | 367 DCHECK(thread); |
| 386 int proc_self_task = OpenProcTaskFd(proc_fd_); | 368 int proc_self_task = OpenProcTaskFd(proc_fd_); |
| 387 PCHECK(proc_self_task >= 0); | 369 PCHECK(proc_self_task >= 0); |
| 388 SafeScopedFD task_closer(&proc_self_task); | 370 SafeScopedFD task_closer(&proc_self_task); |
| 389 CHECK( | 371 CHECK( |
| 390 sandbox::ThreadHelpers::StopThreadAndWatchProcFS(proc_self_task, thread)); | 372 sandbox::ThreadHelpers::StopThreadAndWatchProcFS(proc_self_task, thread)); |
| 391 } | 373 } |
| 392 | 374 |
| 393 } // namespace content | 375 } // namespace content |
| OLD | NEW |