Chromium Code Reviews| Index: sandbox/linux/seccomp-bpf/sandbox_bpf.cc |
| diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc |
| index 6926b5dfdd16c4b8df2dcc0f8a63d072cf0abcc4..e0c8937d39d536360cf0c4ae5102ecc4d337ac70 100644 |
| --- a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc |
| +++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc |
| @@ -7,11 +7,26 @@ |
| #include "sandbox/linux/seccomp-bpf/syscall_iterator.h" |
| #include "sandbox/linux/seccomp-bpf/verifier.h" |
| +namespace { |
| + |
| +void WriteFailedStderrSetupMessage(int out_fd) { |
| + const char* error_string = strerror(errno); |
| + static const char msg[] = "Failed to set up stderr: "; |
| + if (HANDLE_EINTR(write(out_fd, msg, sizeof(msg)-1)) > 0 && error_string && |
| + HANDLE_EINTR(write(out_fd, error_string, strlen(error_string))) > 0 && |
| + HANDLE_EINTR(write(out_fd, "\n", 1))) { |
|
Markus (顧孟勤)
2012/10/26 23:14:11
After this change, do we still expect to see these
jln (very slow on Chromium)
2012/10/29 21:15:37
That makes sense. But let's land a simple, easy to
|
| + } |
| +} |
| + |
| +} // namespace |
| + |
| // The kernel gives us a sandbox, we turn it into a playground :-) |
| // This is version 2 of the playground; version 1 was built on top of |
| // pre-BPF seccomp mode. |
| namespace playground2 { |
| +const int kExpectedExitCode = 100; |
| + |
| // We define a really simple sandbox policy. It is just good enough for us |
| // to tell that the sandbox has actually been activated. |
| ErrorCode Sandbox::probeEvaluator(int signo) { |
| @@ -30,7 +45,7 @@ ErrorCode Sandbox::probeEvaluator(int signo) { |
| void Sandbox::probeProcess(void) { |
| if (syscall(__NR_getpid) < 0 && errno == EPERM) { |
| - syscall(__NR_exit_group, (intptr_t)100); |
| + syscall(__NR_exit_group, static_cast<intptr_t>(kExpectedExitCode)); |
| } |
| } |
| @@ -51,7 +66,7 @@ void Sandbox::tryVsyscallProcess(void) { |
| // vsyscall=emulate and some versions of the seccomp BPF patch |
| // we may get SIGKILL-ed. Detect this! |
| if (time(¤t_time) != static_cast<time_t>(-1)) { |
| - syscall(__NR_exit_group, (intptr_t)100); |
| + syscall(__NR_exit_group, static_cast<intptr_t>(kExpectedExitCode)); |
| } |
| } |
| @@ -70,6 +85,10 @@ bool Sandbox::RunFunctionInPolicy(void (*CodeInSandbox)(), |
| SANDBOX_DIE("pipe() failed"); |
| } |
| + if (fds[0] <= 2 || fds[1] <= 2) { |
| + SANDBOX_DIE("Process started without standard file descriptors"); |
| + } |
| + |
| pid_t pid = fork(); |
| if (pid < 0) { |
| // Die if we cannot fork(). We would probably fail a little later |
| @@ -87,29 +106,37 @@ bool Sandbox::RunFunctionInPolicy(void (*CodeInSandbox)(), |
| // Test a very simple sandbox policy to verify that we can |
| // successfully turn on sandboxing. |
| Die::EnableSimpleExit(); |
| - errno = 0; |
| - if (HANDLE_EINTR(close(fds[0])) || |
| - HANDLE_EINTR(dup2(fds[1], 2)) != 2 || |
| - HANDLE_EINTR(close(fds[1]))) { |
| - const char* error_string = strerror(errno); |
| - static const char msg[] = "Failed to set up stderr: "; |
| - if (HANDLE_EINTR(write(fds[1], msg, sizeof(msg)-1)) > 0 && error_string && |
| - HANDLE_EINTR(write(fds[1], error_string, strlen(error_string))) > 0 && |
| - HANDLE_EINTR(write(fds[1], "\n", 1))) { |
| - } |
| - } else { |
| - evaluators_.clear(); |
| - setSandboxPolicy(syscallEvaluator, NULL); |
| - setProcFd(proc_fd); |
| - // By passing "quiet=true" to "startSandboxInternal()" we suppress |
| - // messages for expected and benign failures (e.g. if the current |
| - // kernel lacks support for BPF filters). |
| - startSandboxInternal(true); |
| - |
| - // Run our code in the sandbox |
| - CodeInSandbox(); |
| + if (HANDLE_EINTR(close(fds[0]))) { |
| + WriteFailedStderrSetupMessage(fds[1]); |
| + SANDBOX_DIE(NULL); |
| + } |
| + if (HANDLE_EINTR(dup2(fds[1], 2)) != 2) { |
|
Markus (顧孟勤)
2012/10/26 23:14:11
Try calling HANDLE_EINTR(close(2)) first and ignor
|
| + // Stderr could very well be a file descriptor to .xsession-errors, or |
| + // another file, which could be backed by a file system that could cause |
| + // dup2 to fail while trying to close stderr. It's important that we do |
| + // not fail on trying to close stderr. |
| + // If dup2 fails here, we will continue normally, this means that our |
| + // parent won't cause a fatal failure if something writes to stderr in |
| + // this child. |
|
Markus (顧孟勤)
2012/10/26 23:14:11
Do you still want this to be fatal in debug builds
jln (very slow on Chromium)
2012/10/29 21:15:37
Yeah, the first iteration of this patch, as you ca
|
| } |
| + if (HANDLE_EINTR(close(fds[1]))) { |
| + WriteFailedStderrSetupMessage(fds[1]); |
| + SANDBOX_DIE(NULL); |
| + } |
| + |
| + evaluators_.clear(); |
| + setSandboxPolicy(syscallEvaluator, NULL); |
| + setProcFd(proc_fd); |
| + |
| + // By passing "quiet=true" to "startSandboxInternal()" we suppress |
| + // messages for expected and benign failures (e.g. if the current |
| + // kernel lacks support for BPF filters). |
| + startSandboxInternal(true); |
| + |
| + // Run our code in the sandbox. |
| + CodeInSandbox(); |
|
Markus (顧孟勤)
2012/10/26 23:14:11
I'd prefer a blank line before the comment, as I f
jln (very slow on Chromium)
2012/10/29 21:15:37
Done.
|
| + // CodeInSandbox() is not supposed to return here. |
| SANDBOX_DIE(NULL); |
| } |
| @@ -124,7 +151,7 @@ bool Sandbox::RunFunctionInPolicy(void (*CodeInSandbox)(), |
| if (HANDLE_EINTR(waitpid(pid, &status, 0)) != pid) { |
| SANDBOX_DIE("waitpid() failed unexpectedly"); |
| } |
| - bool rc = WIFEXITED(status) && WEXITSTATUS(status) == 100; |
| + bool rc = WIFEXITED(status) && WEXITSTATUS(status) == kExpectedExitCode; |
| // If we fail to support sandboxing, there might be an additional |
| // error message. If so, this was an entirely unexpected and fatal |