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 |