summaryrefslogtreecommitdiffstats
path: root/sandbox/linux
diff options
context:
space:
mode:
authorjln@chromium.org <jln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-16 21:57:35 +0000
committerjln@chromium.org <jln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-16 21:57:35 +0000
commit70d19da03e8edc5610bc5c8fff5cc1fbca5e37c8 (patch)
treeb142a2de4d51baa191b905b17dda0a3850ba2eba /sandbox/linux
parentd7e04f6545160d93b31f6a270117373c617761f8 (diff)
downloadchromium_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/linux')
-rw-r--r--sandbox/linux/seccomp-bpf/sandbox_bpf.cc46
-rw-r--r--sandbox/linux/seccomp-bpf/sandbox_bpf.h6
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(&current_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,