diff options
author | jln@chromium.org <jln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-16 21:57:35 +0000 |
---|---|---|
committer | jln@chromium.org <jln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-16 21:57:35 +0000 |
commit | 70d19da03e8edc5610bc5c8fff5cc1fbca5e37c8 (patch) | |
tree | b142a2de4d51baa191b905b17dda0a3850ba2eba /sandbox | |
parent | d7e04f6545160d93b31f6a270117373c617761f8 (diff) | |
download | chromium_src-70d19da03e8edc5610bc5c8fff5cc1fbca5e37c8.zip chromium_src-70d19da03e8edc5610bc5c8fff5cc1fbca5e37c8.tar.gz chromium_src-70d19da03e8edc5610bc5c8fff5cc1fbca5e37c8.tar.bz2 |
Seccomp Sandbox: detect a bug with old glibcs
With some version of the Seccomp BPF kernel patch, an old glibc
and a kernel using vsyscall=emulate would cause a SIGKILL under a
seccomp BPF policy.
We now detect this condition in supportsSeccompSandbox().
BUG=
TEST=
Review URL: https://chromiumcodereview.appspot.com/10703183
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@146902 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sandbox')
-rw-r--r-- | sandbox/linux/seccomp-bpf/sandbox_bpf.cc | 46 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf/sandbox_bpf.h | 6 |
2 files changed, 46 insertions, 6 deletions
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc index 7634ac3..ffbf7cf 100644 --- a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc +++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <time.h> + #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" #include "sandbox/linux/seccomp-bpf/verifier.h" @@ -26,7 +28,33 @@ Sandbox::ErrorCode Sandbox::probeEvaluator(int signo) { } } -bool Sandbox::kernelSupportSeccompBPF(int proc_fd) { +void Sandbox::probeProcess(void) { + if (syscall(__NR_getpid) < 0 && errno == EPERM) { + syscall(__NR_exit_group, (intptr_t)100); + } +} + +Sandbox::ErrorCode Sandbox::allowAllEvaluator(int signo) { + if (signo < static_cast<int>(MIN_SYSCALL) || + signo > static_cast<int>(MAX_SYSCALL)) { + return ENOSYS; + } + return Sandbox::SB_ALLOWED; +} + +void Sandbox::tryVsyscallProcess(void) { + time_t current_time; + // time() is implemented as a vsyscall. With an older glibc, with + // 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); + } +} + +bool Sandbox::RunFunctionInPolicy(void (*CodeInSandbox)(), + EvaluateSyscall syscallEvaluator, + int proc_fd) { // Block all signals before forking a child process. This prevents an // attacker from manipulating our test by sending us an unexpected signal. sigset_t oldMask, newMask; @@ -63,17 +91,16 @@ bool Sandbox::kernelSupportSeccompBPF(int proc_fd) { if (HANDLE_EINTR(write(fds[1], msg, sizeof(msg)-1))) { } } else { evaluators_.clear(); - setSandboxPolicy(probeEvaluator, NULL); + setSandboxPolicy(syscallEvaluator, NULL); setProcFd(proc_fd); startSandbox(); - if (syscall(__NR_getpid) < 0 && errno == EPERM) { - syscall(__NR_exit_group, (intptr_t)100); - } + // Run our code in the sandbox + CodeInSandbox(); } die(NULL); } - // In the parent process + // In the parent process. if (HANDLE_EINTR(close(fds[1]))) { die("close() failed"); } @@ -107,6 +134,13 @@ bool Sandbox::kernelSupportSeccompBPF(int proc_fd) { } return rc; + +} + +bool Sandbox::kernelSupportSeccompBPF(int proc_fd) { + return RunFunctionInPolicy(probeProcess, Sandbox::probeEvaluator, proc_fd) && + RunFunctionInPolicy(tryVsyscallProcess, Sandbox::allowAllEvaluator, + proc_fd); } Sandbox::SandboxStatus Sandbox::supportsSeccompSandbox(int proc_fd) { diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.h b/sandbox/linux/seccomp-bpf/sandbox_bpf.h index d545dd2..d97aeaf 100644 --- a/sandbox/linux/seccomp-bpf/sandbox_bpf.h +++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.h @@ -343,7 +343,13 @@ class Sandbox { typedef std::map<std::pair<TrapFnc, const void *>, int> TrapIds; static ErrorCode probeEvaluator(int signo) __attribute__((const)); + static void probeProcess(void); + static ErrorCode allowAllEvaluator(int signo); + static void tryVsyscallProcess(void); static bool kernelSupportSeccompBPF(int proc_fd); + static bool RunFunctionInPolicy(void (*function)(), + EvaluateSyscall syscallEvaluator, + int proc_fd); static bool isSingleThreaded(int proc_fd); static bool disableFilesystem(); static void policySanityChecks(EvaluateSyscall syscallEvaluator, |