summaryrefslogtreecommitdiffstats
path: root/sandbox/linux/seccomp-bpf
diff options
context:
space:
mode:
authorjln@chromium.org <jln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-27 07:51:38 +0000
committerjln@chromium.org <jln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-27 07:51:38 +0000
commit232f6e1162c61c98d3f03e160f86081121fd4b47 (patch)
tree62e39e41324b3924c2160015dc730c19c00f9835 /sandbox/linux/seccomp-bpf
parent80c09f18620663ca240611533e7cc875c83d35d8 (diff)
downloadchromium_src-232f6e1162c61c98d3f03e160f86081121fd4b47.zip
chromium_src-232f6e1162c61c98d3f03e160f86081121fd4b47.tar.gz
chromium_src-232f6e1162c61c98d3f03e160f86081121fd4b47.tar.bz2
Linux sandbox: add test to ensure that pread64 can be forwarded.
Make sure that the pread64() system call can be forwarded from seccomp-bpf trap handlers. BUG=388978 NOTRY=true Review URL: https://codereview.chromium.org/348853006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@280262 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sandbox/linux/seccomp-bpf')
-rw-r--r--sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc105
-rw-r--r--sandbox/linux/seccomp-bpf/syscall_unittest.cc4
2 files changed, 101 insertions, 8 deletions
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc
index 06ba209..95fcbc6 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc
@@ -34,6 +34,7 @@
#include "sandbox/linux/seccomp-bpf/verifier.h"
#include "sandbox/linux/services/broker_process.h"
#include "sandbox/linux/services/linux_syscalls.h"
+#include "sandbox/linux/tests/scoped_temporary_file.h"
#include "sandbox/linux/tests/unit_tests.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -53,6 +54,17 @@ namespace {
const int kExpectedReturnValue = 42;
const char kSandboxDebuggingEnv[] = "CHROME_SANDBOX_DEBUGGING";
+// Set the global environment to allow the use of UnsafeTrap() policies.
+void EnableUnsafeTraps() {
+ // The use of UnsafeTrap() causes us to print a warning message. This is
+ // generally desirable, but it results in the unittest failing, as it doesn't
+ // expect any messages on "stderr". So, temporarily disable messages. The
+ // BPF_TEST() is guaranteed to turn messages back on, after the policy
+ // function has completed.
+ setenv(kSandboxDebuggingEnv, "t", 0);
+ Die::SuppressInfoMessages(true);
+}
+
// This test should execute no matter whether we have kernel support. So,
// we make it a TEST() instead of a BPF_TEST().
TEST(SandboxBPF, DISABLE_ON_TSAN(CallSupports)) {
@@ -480,13 +492,10 @@ intptr_t CountSyscalls(const struct arch_seccomp_data& args, void* aux) {
}
ErrorCode GreyListedPolicy(SandboxBPF* sandbox, int sysno, int* aux) {
- // The use of UnsafeTrap() causes us to print a warning message. This is
- // generally desirable, but it results in the unittest failing, as it doesn't
- // expect any messages on "stderr". So, temporarily disable messages. The
- // BPF_TEST() is guaranteed to turn messages back on, after the policy
- // function has completed.
- setenv(kSandboxDebuggingEnv, "t", 0);
- Die::SuppressInfoMessages(true);
+ // Set the global environment for unsafe traps once.
+ if (sysno == MIN_SYSCALL) {
+ EnableUnsafeTraps();
+ }
// Some system calls must always be allowed, if our policy wants to make
// use of UnsafeTrap()
@@ -2059,6 +2068,88 @@ SANDBOX_TEST(SandboxBPF, DISABLE_ON_TSAN(SeccompRetTrace)) {
}
}
+// Android does not expose pread64 nor pwrite64.
+#if !defined(OS_ANDROID)
+
+bool FullPwrite64(int fd, const char* buffer, size_t count, off64_t offset) {
+ while (count > 0) {
+ const ssize_t transfered =
+ HANDLE_EINTR(pwrite64(fd, buffer, count, offset));
+ if (transfered <= 0 || static_cast<size_t>(transfered) > count) {
+ return false;
+ }
+ count -= transfered;
+ buffer += transfered;
+ offset += transfered;
+ }
+ return true;
+}
+
+bool FullPread64(int fd, char* buffer, size_t count, off64_t offset) {
+ while (count > 0) {
+ const ssize_t transfered = HANDLE_EINTR(pread64(fd, buffer, count, offset));
+ if (transfered <= 0 || static_cast<size_t>(transfered) > count) {
+ return false;
+ }
+ count -= transfered;
+ buffer += transfered;
+ offset += transfered;
+ }
+ return true;
+}
+
+bool pread_64_was_forwarded = false;
+
+class TrapPread64Policy : public SandboxBPFPolicy {
+ public:
+ TrapPread64Policy() {}
+ virtual ~TrapPread64Policy() {}
+
+ virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
+ int system_call_number) const OVERRIDE {
+ // Set the global environment for unsafe traps once.
+ if (system_call_number == MIN_SYSCALL) {
+ EnableUnsafeTraps();
+ }
+
+ if (system_call_number == __NR_pread64) {
+ return sandbox_compiler->UnsafeTrap(ForwardPreadHandler, NULL);
+ }
+ return ErrorCode(ErrorCode::ERR_ALLOWED);
+ }
+
+ private:
+ static intptr_t ForwardPreadHandler(const struct arch_seccomp_data& args,
+ void* aux) {
+ BPF_ASSERT(args.nr == __NR_pread64);
+ pread_64_was_forwarded = true;
+
+ return SandboxBPF::ForwardSyscall(args);
+ }
+ DISALLOW_COPY_AND_ASSIGN(TrapPread64Policy);
+};
+
+// pread(2) takes a 64 bits offset. On 32 bits systems, it will be split
+// between two arguments. In this test, we make sure that ForwardSyscall() can
+// forward it properly.
+BPF_TEST_C(SandboxBPF, Pread64, TrapPread64Policy) {
+ ScopedTemporaryFile temp_file;
+ const uint64_t kLargeOffset = (static_cast<uint64_t>(1) << 32) | 0xBEEF;
+ const char kTestString[] = "This is a test!";
+ BPF_ASSERT(FullPwrite64(
+ temp_file.fd(), kTestString, sizeof(kTestString), kLargeOffset));
+
+ char read_test_string[sizeof(kTestString)] = {0};
+ BPF_ASSERT(FullPread64(temp_file.fd(),
+ read_test_string,
+ sizeof(read_test_string),
+ kLargeOffset));
+ BPF_ASSERT_EQ(0, memcmp(kTestString, read_test_string, sizeof(kTestString)));
+ BPF_ASSERT(pread_64_was_forwarded);
+}
+
+#endif // !defined(OS_ANDROID)
+
} // namespace
} // namespace sandbox
diff --git a/sandbox/linux/seccomp-bpf/syscall_unittest.cc b/sandbox/linux/seccomp-bpf/syscall_unittest.cc
index 80b5079..4e142f4 100644
--- a/sandbox/linux/seccomp-bpf/syscall_unittest.cc
+++ b/sandbox/linux/seccomp-bpf/syscall_unittest.cc
@@ -2,10 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "sandbox/linux/seccomp-bpf/syscall.h"
+
#include <asm/unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/syscall.h>
+#include <sys/types.h>
#include <unistd.h>
#include <vector>
@@ -15,7 +18,6 @@
#include "build/build_config.h"
#include "sandbox/linux/seccomp-bpf/bpf_tests.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
-#include "sandbox/linux/seccomp-bpf/syscall.h"
#include "sandbox/linux/tests/unit_tests.h"
#include "testing/gtest/include/gtest/gtest.h"