| 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 |