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