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 "sandbox/linux/seccomp-bpf/sandbox_bpf.h" | 5 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" |
6 | 6 |
7 // Some headers on Android are missing cdefs: crbug.com/172337. | 7 // Some headers on Android are missing cdefs: crbug.com/172337. |
8 // (We can't use OS_ANDROID here since build_config.h is not included). | 8 // (We can't use OS_ANDROID here since build_config.h is not included). |
9 #if defined(ANDROID) | 9 #if defined(ANDROID) |
10 #include <sys/cdefs.h> | 10 #include <sys/cdefs.h> |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 bool IsSingleThreaded(int proc_fd) { | 97 bool IsSingleThreaded(int proc_fd) { |
98 if (proc_fd < 0) { | 98 if (proc_fd < 0) { |
99 // Cannot determine whether program is single-threaded. Hope for | 99 // Cannot determine whether program is single-threaded. Hope for |
100 // the best... | 100 // the best... |
101 return true; | 101 return true; |
102 } | 102 } |
103 | 103 |
104 struct stat sb; | 104 struct stat sb; |
105 int task = -1; | 105 int task = -1; |
106 if ((task = openat(proc_fd, "self/task", O_RDONLY | O_DIRECTORY)) < 0 || | 106 if ((task = openat(proc_fd, "self/task", O_RDONLY | O_DIRECTORY)) < 0 || |
107 fstat(task, &sb) != 0 || sb.st_nlink != 3 || HANDLE_EINTR(close(task))) { | 107 fstat(task, &sb) != 0 || sb.st_nlink != 3 || IGNORE_EINTR(close(task))) { |
108 if (task >= 0) { | 108 if (task >= 0) { |
109 if (HANDLE_EINTR(close(task))) { | 109 if (IGNORE_EINTR(close(task))) { |
110 } | 110 } |
111 } | 111 } |
112 return false; | 112 return false; |
113 } | 113 } |
114 return true; | 114 return true; |
115 } | 115 } |
116 | 116 |
117 bool IsDenied(const ErrorCode& code) { | 117 bool IsDenied(const ErrorCode& code) { |
118 return (code.err() & SECCOMP_RET_ACTION) == SECCOMP_RET_TRAP || | 118 return (code.err() & SECCOMP_RET_ACTION) == SECCOMP_RET_TRAP || |
119 (code.err() >= (SECCOMP_RET_ERRNO + ErrorCode::ERR_MIN_ERRNO) && | 119 (code.err() >= (SECCOMP_RET_ERRNO + ErrorCode::ERR_MIN_ERRNO) && |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 SANDBOX_DIE("fork() failed unexpectedly"); | 280 SANDBOX_DIE("fork() failed unexpectedly"); |
281 } | 281 } |
282 | 282 |
283 // In the child process | 283 // In the child process |
284 if (!pid) { | 284 if (!pid) { |
285 // Test a very simple sandbox policy to verify that we can | 285 // Test a very simple sandbox policy to verify that we can |
286 // successfully turn on sandboxing. | 286 // successfully turn on sandboxing. |
287 Die::EnableSimpleExit(); | 287 Die::EnableSimpleExit(); |
288 | 288 |
289 errno = 0; | 289 errno = 0; |
290 if (HANDLE_EINTR(close(fds[0]))) { | 290 if (IGNORE_EINTR(close(fds[0]))) { |
291 // This call to close() has been failing in strange ways. See | 291 // This call to close() has been failing in strange ways. See |
292 // crbug.com/152530. So we only fail in debug mode now. | 292 // crbug.com/152530. So we only fail in debug mode now. |
293 #if !defined(NDEBUG) | 293 #if !defined(NDEBUG) |
294 WriteFailedStderrSetupMessage(fds[1]); | 294 WriteFailedStderrSetupMessage(fds[1]); |
295 SANDBOX_DIE(NULL); | 295 SANDBOX_DIE(NULL); |
296 #endif | 296 #endif |
297 } | 297 } |
298 if (HANDLE_EINTR(dup2(fds[1], 2)) != 2) { | 298 if (HANDLE_EINTR(dup2(fds[1], 2)) != 2) { |
299 // Stderr could very well be a file descriptor to .xsession-errors, or | 299 // Stderr could very well be a file descriptor to .xsession-errors, or |
300 // another file, which could be backed by a file system that could cause | 300 // another file, which could be backed by a file system that could cause |
301 // dup2 to fail while trying to close stderr. It's important that we do | 301 // dup2 to fail while trying to close stderr. It's important that we do |
302 // not fail on trying to close stderr. | 302 // not fail on trying to close stderr. |
303 // If dup2 fails here, we will continue normally, this means that our | 303 // If dup2 fails here, we will continue normally, this means that our |
304 // parent won't cause a fatal failure if something writes to stderr in | 304 // parent won't cause a fatal failure if something writes to stderr in |
305 // this child. | 305 // this child. |
306 #if !defined(NDEBUG) | 306 #if !defined(NDEBUG) |
307 // In DEBUG builds, we still want to get a report. | 307 // In DEBUG builds, we still want to get a report. |
308 WriteFailedStderrSetupMessage(fds[1]); | 308 WriteFailedStderrSetupMessage(fds[1]); |
309 SANDBOX_DIE(NULL); | 309 SANDBOX_DIE(NULL); |
310 #endif | 310 #endif |
311 } | 311 } |
312 if (HANDLE_EINTR(close(fds[1]))) { | 312 if (IGNORE_EINTR(close(fds[1]))) { |
313 // This call to close() has been failing in strange ways. See | 313 // This call to close() has been failing in strange ways. See |
314 // crbug.com/152530. So we only fail in debug mode now. | 314 // crbug.com/152530. So we only fail in debug mode now. |
315 #if !defined(NDEBUG) | 315 #if !defined(NDEBUG) |
316 WriteFailedStderrSetupMessage(fds[1]); | 316 WriteFailedStderrSetupMessage(fds[1]); |
317 SANDBOX_DIE(NULL); | 317 SANDBOX_DIE(NULL); |
318 #endif | 318 #endif |
319 } | 319 } |
320 | 320 |
321 SetSandboxPolicyDeprecated(syscall_evaluator, aux); | 321 SetSandboxPolicyDeprecated(syscall_evaluator, aux); |
322 StartSandbox(); | 322 StartSandbox(); |
323 | 323 |
324 // Run our code in the sandbox. | 324 // Run our code in the sandbox. |
325 code_in_sandbox(); | 325 code_in_sandbox(); |
326 | 326 |
327 // code_in_sandbox() is not supposed to return here. | 327 // code_in_sandbox() is not supposed to return here. |
328 SANDBOX_DIE(NULL); | 328 SANDBOX_DIE(NULL); |
329 } | 329 } |
330 | 330 |
331 // In the parent process. | 331 // In the parent process. |
332 if (HANDLE_EINTR(close(fds[1]))) { | 332 if (IGNORE_EINTR(close(fds[1]))) { |
333 SANDBOX_DIE("close() failed"); | 333 SANDBOX_DIE("close() failed"); |
334 } | 334 } |
335 if (sigprocmask(SIG_SETMASK, &old_mask, NULL)) { | 335 if (sigprocmask(SIG_SETMASK, &old_mask, NULL)) { |
336 SANDBOX_DIE("sigprocmask() failed"); | 336 SANDBOX_DIE("sigprocmask() failed"); |
337 } | 337 } |
338 int status; | 338 int status; |
339 if (HANDLE_EINTR(waitpid(pid, &status, 0)) != pid) { | 339 if (HANDLE_EINTR(waitpid(pid, &status, 0)) != pid) { |
340 SANDBOX_DIE("waitpid() failed unexpectedly"); | 340 SANDBOX_DIE("waitpid() failed unexpectedly"); |
341 } | 341 } |
342 bool rc = WIFEXITED(status) && WEXITSTATUS(status) == kExpectedExitCode; | 342 bool rc = WIFEXITED(status) && WEXITSTATUS(status) == kExpectedExitCode; |
343 | 343 |
344 // If we fail to support sandboxing, there might be an additional | 344 // If we fail to support sandboxing, there might be an additional |
345 // error message. If so, this was an entirely unexpected and fatal | 345 // error message. If so, this was an entirely unexpected and fatal |
346 // failure. We should report the failure and somebody must fix | 346 // failure. We should report the failure and somebody must fix |
347 // things. This is probably a security-critical bug in the sandboxing | 347 // things. This is probably a security-critical bug in the sandboxing |
348 // code. | 348 // code. |
349 if (!rc) { | 349 if (!rc) { |
350 char buf[4096]; | 350 char buf[4096]; |
351 ssize_t len = HANDLE_EINTR(read(fds[0], buf, sizeof(buf) - 1)); | 351 ssize_t len = HANDLE_EINTR(read(fds[0], buf, sizeof(buf) - 1)); |
352 if (len > 0) { | 352 if (len > 0) { |
353 while (len > 1 && buf[len - 1] == '\n') { | 353 while (len > 1 && buf[len - 1] == '\n') { |
354 --len; | 354 --len; |
355 } | 355 } |
356 buf[len] = '\000'; | 356 buf[len] = '\000'; |
357 SANDBOX_DIE(buf); | 357 SANDBOX_DIE(buf); |
358 } | 358 } |
359 } | 359 } |
360 if (HANDLE_EINTR(close(fds[0]))) { | 360 if (IGNORE_EINTR(close(fds[0]))) { |
361 SANDBOX_DIE("close() failed"); | 361 SANDBOX_DIE("close() failed"); |
362 } | 362 } |
363 | 363 |
364 return rc; | 364 return rc; |
365 } | 365 } |
366 | 366 |
367 bool Sandbox::KernelSupportSeccompBPF() { | 367 bool Sandbox::KernelSupportSeccompBPF() { |
368 return RunFunctionInPolicy(ProbeProcess, ProbeEvaluator, 0) && | 368 return RunFunctionInPolicy(ProbeProcess, ProbeEvaluator, 0) && |
369 RunFunctionInPolicy(TryVsyscallProcess, AllowAllEvaluator, 0); | 369 RunFunctionInPolicy(TryVsyscallProcess, AllowAllEvaluator, 0); |
370 } | 370 } |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 // In the future, we might want to tighten this requirement. | 444 // In the future, we might want to tighten this requirement. |
445 } | 445 } |
446 if (!IsSingleThreaded(proc_fd_)) { | 446 if (!IsSingleThreaded(proc_fd_)) { |
447 SANDBOX_DIE("Cannot start sandbox, if process is already multi-threaded"); | 447 SANDBOX_DIE("Cannot start sandbox, if process is already multi-threaded"); |
448 } | 448 } |
449 | 449 |
450 // We no longer need access to any files in /proc. We want to do this | 450 // We no longer need access to any files in /proc. We want to do this |
451 // before installing the filters, just in case that our policy denies | 451 // before installing the filters, just in case that our policy denies |
452 // close(). | 452 // close(). |
453 if (proc_fd_ >= 0) { | 453 if (proc_fd_ >= 0) { |
454 if (HANDLE_EINTR(close(proc_fd_))) { | 454 if (IGNORE_EINTR(close(proc_fd_))) { |
455 SANDBOX_DIE("Failed to close file descriptor for /proc"); | 455 SANDBOX_DIE("Failed to close file descriptor for /proc"); |
456 } | 456 } |
457 proc_fd_ = -1; | 457 proc_fd_ = -1; |
458 } | 458 } |
459 | 459 |
460 // Install the filters. | 460 // Install the filters. |
461 InstallFilter(); | 461 InstallFilter(); |
462 | 462 |
463 // We are now inside the sandbox. | 463 // We are now inside the sandbox. |
464 status_ = STATUS_ENABLED; | 464 status_ = STATUS_ENABLED; |
(...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1009 &*conds_->insert(failed).first); | 1009 &*conds_->insert(failed).first); |
1010 } | 1010 } |
1011 | 1011 |
1012 ErrorCode Sandbox::Kill(const char* msg) { | 1012 ErrorCode Sandbox::Kill(const char* msg) { |
1013 return Trap(BpfFailure, const_cast<char*>(msg)); | 1013 return Trap(BpfFailure, const_cast<char*>(msg)); |
1014 } | 1014 } |
1015 | 1015 |
1016 Sandbox::SandboxStatus Sandbox::status_ = STATUS_UNKNOWN; | 1016 Sandbox::SandboxStatus Sandbox::status_ = STATUS_UNKNOWN; |
1017 | 1017 |
1018 } // namespace playground2 | 1018 } // namespace playground2 |
OLD | NEW |