diff options
author | kaliamoorthi <kaliamoorthi@chromium.org> | 2015-02-20 03:08:48 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-02-20 11:09:46 +0000 |
commit | da7202250804e59b1584927bff20f658be70fda2 (patch) | |
tree | a33babf902ef4b0d49473d031f4cde18b29c1900 | |
parent | 07064b0ef19984fca2655ebc16f6d342fa93859e (diff) | |
download | chromium_src-da7202250804e59b1584927bff20f658be70fda2.zip chromium_src-da7202250804e59b1584927bff20f658be70fda2.tar.gz chromium_src-da7202250804e59b1584927bff20f658be70fda2.tar.bz2 |
Revert of bpf_dsl: Change bpf_dsl_unittests into actual standalone unit tests (patchset #3 id:40001 of https://codereview.chromium.org/940693004/)
Reason for revert:
A related CL was reverted. Reverting this to ensure that this does not cause a failure due to the revert.
Original issue's description:
> bpf_dsl: Change bpf_dsl_unittests into actual standalone unit tests
>
> Previously they were more like integration tests that relied on
> seccomp-bpf for installing the policies and executing them via live
> system calls.
>
> BUG=449357
>
> Committed: https://crrev.com/fdb1befee90e6849a1743fcacbe01521261a6366
> Cr-Commit-Position: refs/heads/master@{#317238}
TBR=jln@chromium.org,mdempsky@chromium.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=449357
Review URL: https://codereview.chromium.org/944823002
Cr-Commit-Position: refs/heads/master@{#317285}
-rw-r--r-- | sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc | 225 | ||||
-rw-r--r-- | sandbox/linux/bpf_dsl/seccomp_macros.h | 2 | ||||
-rw-r--r-- | sandbox/linux/bpf_dsl/trap_registry.h | 4 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf/trap.h | 6 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf/verifier.h | 3 |
5 files changed, 79 insertions, 161 deletions
diff --git a/sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc b/sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc index 168eaec..cffadc5 100644 --- a/sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc +++ b/sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc @@ -16,95 +16,51 @@ #include "base/macros.h" #include "build/build_config.h" #include "sandbox/linux/bpf_dsl/bpf_dsl_impl.h" -#include "sandbox/linux/bpf_dsl/codegen.h" #include "sandbox/linux/bpf_dsl/policy.h" -#include "sandbox/linux/bpf_dsl/policy_compiler.h" -#include "sandbox/linux/bpf_dsl/seccomp_macros.h" -#include "sandbox/linux/bpf_dsl/trap_registry.h" +#include "sandbox/linux/seccomp-bpf/bpf_tests.h" #include "sandbox/linux/seccomp-bpf/errorcode.h" -#include "sandbox/linux/seccomp-bpf/verifier.h" +#include "sandbox/linux/seccomp-bpf/syscall.h" #include "testing/gtest/include/gtest/gtest.h" #define CASES SANDBOX_BPF_DSL_CASES +// Helper macro to assert that invoking system call |sys| directly via +// Syscall::Call with arguments |...| returns |res|. +// Errors can be asserted by specifying a value like "-EINVAL". +#define ASSERT_SYSCALL_RESULT(res, sys, ...) \ + BPF_ASSERT_EQ(res, Stubs::sys(__VA_ARGS__)) + namespace sandbox { namespace bpf_dsl { namespace { -// Helper function to construct fake arch_seccomp_data objects. -struct arch_seccomp_data FakeSyscall(int nr, - uint64_t p0 = 0, - uint64_t p1 = 0, - uint64_t p2 = 0, - uint64_t p3 = 0, - uint64_t p4 = 0, - uint64_t p5 = 0) { - // Made up program counter for syscall address. - const uint64_t kFakePC = 0x543210; - - struct arch_seccomp_data data = { - nr, - SECCOMP_ARCH, - kFakePC, - { - p0, p1, p2, p3, p4, p5, - }, - }; - - return data; -} - -class FakeTrapRegistry : public TrapRegistry { +// Type safe stubs for tested system calls. +class Stubs { public: - FakeTrapRegistry() : next_id_(1) {} - virtual ~FakeTrapRegistry() {} - - uint16_t Add(TrapFnc fnc, const void* aux, bool safe) override { - EXPECT_NE(0U, next_id_); - return next_id_++; + static int getpgid(pid_t pid) { return Syscall::Call(__NR_getpgid, pid); } + static int setuid(uid_t uid) { return Syscall::Call(__NR_setuid, uid); } + static int setgid(gid_t gid) { return Syscall::Call(__NR_setgid, gid); } + static int setpgid(pid_t pid, pid_t pgid) { + return Syscall::Call(__NR_setpgid, pid, pgid); } - bool EnableUnsafeTraps() override { - ADD_FAILURE() << "Unimplemented"; - return false; + static int fcntl(int fd, int cmd, unsigned long arg = 0) { + return Syscall::Call(__NR_fcntl, fd, cmd, arg); } - private: - uint16_t next_id_; - - DISALLOW_COPY_AND_ASSIGN(FakeTrapRegistry); -}; - -class PolicyEmulator { - public: - explicit PolicyEmulator(const Policy* policy) : program_(), traps_() { - program_ = *PolicyCompiler(policy, &traps_).Compile(); - } - ~PolicyEmulator() {} - - uint32_t Emulate(const struct arch_seccomp_data& data) const { - const char* err = nullptr; - uint32_t res = Verifier::EvaluateBPF(program_, data, &err); - if (err) { - ADD_FAILURE() << err; - return 0; - } - return res; + static int uname(struct utsname* buf) { + return Syscall::Call(__NR_uname, buf); } - void ExpectAllow(const struct arch_seccomp_data& data) const { - EXPECT_EQ(SECCOMP_RET_ALLOW, Emulate(data)); + static int setresuid(uid_t ruid, uid_t euid, uid_t suid) { + return Syscall::Call(__NR_setresuid, ruid, euid, suid); } - void ExpectErrno(uint16_t err, const struct arch_seccomp_data& data) const { - EXPECT_EQ(SECCOMP_RET_ERRNO | err, Emulate(data)); +#if !defined(ARCH_CPU_X86) + static int socketpair(int domain, int type, int protocol, int sv[2]) { + return Syscall::Call(__NR_socketpair, domain, type, protocol, sv); } - - private: - CodeGen::Program program_; - FakeTrapRegistry traps_; - - DISALLOW_COPY_AND_ASSIGN(PolicyEmulator); +#endif }; class BasicPolicy : public Policy { @@ -127,15 +83,12 @@ class BasicPolicy : public Policy { DISALLOW_COPY_AND_ASSIGN(BasicPolicy); }; -TEST(BPFDSL, Basic) { - BasicPolicy policy; - PolicyEmulator emulator(&policy); +BPF_TEST_C(BPFDSL, Basic, BasicPolicy) { + ASSERT_SYSCALL_RESULT(-EPERM, getpgid, 0); + ASSERT_SYSCALL_RESULT(-EINVAL, getpgid, 1); - emulator.ExpectErrno(EPERM, FakeSyscall(__NR_getpgid, 0)); - emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_getpgid, 1)); - - emulator.ExpectErrno(ENOMEM, FakeSyscall(__NR_setuid, 42)); - emulator.ExpectErrno(ESRCH, FakeSyscall(__NR_setuid, 43)); + ASSERT_SYSCALL_RESULT(-ENOMEM, setuid, 42); + ASSERT_SYSCALL_RESULT(-ESRCH, setuid, 43); } /* On IA-32, socketpair() is implemented via socketcall(). :-( */ @@ -159,30 +112,22 @@ class BooleanLogicPolicy : public Policy { DISALLOW_COPY_AND_ASSIGN(BooleanLogicPolicy); }; -TEST(BPFDSL, BooleanLogic) { - BooleanLogicPolicy policy; - PolicyEmulator emulator(&policy); - - const intptr_t kFakeSV = 0x12345; +BPF_TEST_C(BPFDSL, BooleanLogic, BooleanLogicPolicy) { + int sv[2]; // Acceptable combinations that should return EPERM. - emulator.ExpectErrno( - EPERM, FakeSyscall(__NR_socketpair, AF_UNIX, SOCK_STREAM, 0, kFakeSV)); - emulator.ExpectErrno( - EPERM, FakeSyscall(__NR_socketpair, AF_UNIX, SOCK_DGRAM, 0, kFakeSV)); + ASSERT_SYSCALL_RESULT(-EPERM, socketpair, AF_UNIX, SOCK_STREAM, 0, sv); + ASSERT_SYSCALL_RESULT(-EPERM, socketpair, AF_UNIX, SOCK_DGRAM, 0, sv); // Combinations that are invalid for only one reason; should return EINVAL. - emulator.ExpectErrno( - EINVAL, FakeSyscall(__NR_socketpair, AF_INET, SOCK_STREAM, 0, kFakeSV)); - emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_socketpair, AF_UNIX, - SOCK_SEQPACKET, 0, kFakeSV)); - emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_socketpair, AF_UNIX, - SOCK_STREAM, IPPROTO_TCP, kFakeSV)); + ASSERT_SYSCALL_RESULT(-EINVAL, socketpair, AF_INET, SOCK_STREAM, 0, sv); + ASSERT_SYSCALL_RESULT(-EINVAL, socketpair, AF_UNIX, SOCK_SEQPACKET, 0, sv); + ASSERT_SYSCALL_RESULT( + -EINVAL, socketpair, AF_UNIX, SOCK_STREAM, IPPROTO_TCP, sv); // Completely unacceptable combination; should also return EINVAL. - emulator.ExpectErrno( - EINVAL, FakeSyscall(__NR_socketpair, AF_INET, SOCK_SEQPACKET, IPPROTO_UDP, - kFakeSV)); + ASSERT_SYSCALL_RESULT( + -EINVAL, socketpair, AF_INET, SOCK_SEQPACKET, IPPROTO_UDP, sv); } #endif // !ARCH_CPU_X86 @@ -204,23 +149,20 @@ class MoreBooleanLogicPolicy : public Policy { DISALLOW_COPY_AND_ASSIGN(MoreBooleanLogicPolicy); }; -TEST(BPFDSL, MoreBooleanLogic) { - MoreBooleanLogicPolicy policy; - PolicyEmulator emulator(&policy); - +BPF_TEST_C(BPFDSL, MoreBooleanLogic, MoreBooleanLogicPolicy) { // Expect EPERM if any set to 0. - emulator.ExpectErrno(EPERM, FakeSyscall(__NR_setresuid, 0, 5, 5)); - emulator.ExpectErrno(EPERM, FakeSyscall(__NR_setresuid, 5, 0, 5)); - emulator.ExpectErrno(EPERM, FakeSyscall(__NR_setresuid, 5, 5, 0)); + ASSERT_SYSCALL_RESULT(-EPERM, setresuid, 0, 5, 5); + ASSERT_SYSCALL_RESULT(-EPERM, setresuid, 5, 0, 5); + ASSERT_SYSCALL_RESULT(-EPERM, setresuid, 5, 5, 0); // Expect EAGAIN if all set to 1. - emulator.ExpectErrno(EAGAIN, FakeSyscall(__NR_setresuid, 1, 1, 1)); + ASSERT_SYSCALL_RESULT(-EAGAIN, setresuid, 1, 1, 1); // Expect EINVAL for anything else. - emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_setresuid, 5, 1, 1)); - emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_setresuid, 1, 5, 1)); - emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_setresuid, 1, 1, 5)); - emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_setresuid, 3, 4, 5)); + ASSERT_SYSCALL_RESULT(-EINVAL, setresuid, 5, 1, 1); + ASSERT_SYSCALL_RESULT(-EINVAL, setresuid, 1, 5, 1); + ASSERT_SYSCALL_RESULT(-EINVAL, setresuid, 1, 1, 5); + ASSERT_SYSCALL_RESULT(-EINVAL, setresuid, 3, 4, 5); } static const uintptr_t kDeadBeefAddr = @@ -242,17 +184,13 @@ class ArgSizePolicy : public Policy { DISALLOW_COPY_AND_ASSIGN(ArgSizePolicy); }; -TEST(BPFDSL, ArgSizeTest) { - ArgSizePolicy policy; - PolicyEmulator emulator(&policy); - - emulator.ExpectAllow(FakeSyscall(__NR_uname, 0)); - emulator.ExpectErrno(EPERM, FakeSyscall(__NR_uname, kDeadBeefAddr)); +BPF_TEST_C(BPFDSL, ArgSizeTest, ArgSizePolicy) { + struct utsname buf; + ASSERT_SYSCALL_RESULT(0, uname, &buf); + ASSERT_SYSCALL_RESULT( + -EPERM, uname, reinterpret_cast<struct utsname*>(kDeadBeefAddr)); } -#if 0 -// TODO(mdempsky): This is really an integration test. - class TrappingPolicy : public Policy { public: TrappingPolicy() {} @@ -282,7 +220,6 @@ BPF_TEST_C(BPFDSL, TrapTest, TrappingPolicy) { ASSERT_SYSCALL_RESULT(2, uname, NULL); ASSERT_SYSCALL_RESULT(3, uname, NULL); } -#endif class MaskingPolicy : public Policy { public: @@ -308,23 +245,20 @@ class MaskingPolicy : public Policy { DISALLOW_COPY_AND_ASSIGN(MaskingPolicy); }; -TEST(BPFDSL, MaskTest) { - MaskingPolicy policy; - PolicyEmulator emulator(&policy); - +BPF_TEST_C(BPFDSL, MaskTest, MaskingPolicy) { for (uid_t uid = 0; uid < 0x100; ++uid) { const int expect_errno = (uid & 0xf) == 0 ? EINVAL : EACCES; - emulator.ExpectErrno(expect_errno, FakeSyscall(__NR_setuid, uid)); + ASSERT_SYSCALL_RESULT(-expect_errno, setuid, uid); } for (gid_t gid = 0; gid < 0x100; ++gid) { const int expect_errno = (gid & 0xf0) == 0xf0 ? EINVAL : EACCES; - emulator.ExpectErrno(expect_errno, FakeSyscall(__NR_setgid, gid)); + ASSERT_SYSCALL_RESULT(-expect_errno, setgid, gid); } for (pid_t pid = 0; pid < 0x100; ++pid) { const int expect_errno = (pid & 0xa5) == 0xa0 ? EINVAL : EACCES; - emulator.ExpectErrno(expect_errno, FakeSyscall(__NR_setpgid, pid, 0)); + ASSERT_SYSCALL_RESULT(-expect_errno, setpgid, pid, 0); } } @@ -347,20 +281,17 @@ class ElseIfPolicy : public Policy { DISALLOW_COPY_AND_ASSIGN(ElseIfPolicy); }; -TEST(BPFDSL, ElseIfTest) { - ElseIfPolicy policy; - PolicyEmulator emulator(&policy); - - emulator.ExpectErrno(0, FakeSyscall(__NR_setuid, 0)); +BPF_TEST_C(BPFDSL, ElseIfTest, ElseIfPolicy) { + ASSERT_SYSCALL_RESULT(0, setuid, 0); - emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_setuid, 0x0001)); - emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_setuid, 0x0002)); + ASSERT_SYSCALL_RESULT(-EINVAL, setuid, 0x0001); + ASSERT_SYSCALL_RESULT(-EINVAL, setuid, 0x0002); - emulator.ExpectErrno(EEXIST, FakeSyscall(__NR_setuid, 0x0011)); - emulator.ExpectErrno(EEXIST, FakeSyscall(__NR_setuid, 0x0022)); + ASSERT_SYSCALL_RESULT(-EEXIST, setuid, 0x0011); + ASSERT_SYSCALL_RESULT(-EEXIST, setuid, 0x0022); - emulator.ExpectErrno(EACCES, FakeSyscall(__NR_setuid, 0x0111)); - emulator.ExpectErrno(EACCES, FakeSyscall(__NR_setuid, 0x0222)); + ASSERT_SYSCALL_RESULT(-EACCES, setuid, 0x0111); + ASSERT_SYSCALL_RESULT(-EACCES, setuid, 0x0222); } class SwitchPolicy : public Policy { @@ -384,25 +315,19 @@ class SwitchPolicy : public Policy { DISALLOW_COPY_AND_ASSIGN(SwitchPolicy); }; -TEST(BPFDSL, SwitchTest) { - SwitchPolicy policy; - PolicyEmulator emulator(&policy); - - const int kFakeSockFD = 42; +BPF_TEST_C(BPFDSL, SwitchTest, SwitchPolicy) { + base::ScopedFD sock_fd(socket(AF_UNIX, SOCK_STREAM, 0)); + BPF_ASSERT(sock_fd.is_valid()); - emulator.ExpectErrno(ENOENT, FakeSyscall(__NR_fcntl, kFakeSockFD, F_GETFD)); - emulator.ExpectErrno(ENOENT, FakeSyscall(__NR_fcntl, kFakeSockFD, F_GETFL)); + ASSERT_SYSCALL_RESULT(-ENOENT, fcntl, sock_fd.get(), F_GETFD); + ASSERT_SYSCALL_RESULT(-ENOENT, fcntl, sock_fd.get(), F_GETFL); - emulator.ExpectAllow( - FakeSyscall(__NR_fcntl, kFakeSockFD, F_SETFD, O_CLOEXEC)); - emulator.ExpectErrno(EINVAL, - FakeSyscall(__NR_fcntl, kFakeSockFD, F_SETFD, 0)); + ASSERT_SYSCALL_RESULT(0, fcntl, sock_fd.get(), F_SETFD, O_CLOEXEC); + ASSERT_SYSCALL_RESULT(-EINVAL, fcntl, sock_fd.get(), F_SETFD, 0); - emulator.ExpectErrno(EPERM, - FakeSyscall(__NR_fcntl, kFakeSockFD, F_SETFL, O_RDONLY)); + ASSERT_SYSCALL_RESULT(-EPERM, fcntl, sock_fd.get(), F_SETFL, O_RDONLY); - emulator.ExpectErrno(EACCES, - FakeSyscall(__NR_fcntl, kFakeSockFD, F_DUPFD, 0)); + ASSERT_SYSCALL_RESULT(-EACCES, fcntl, sock_fd.get(), F_DUPFD, 0); } static intptr_t DummyTrap(const struct arch_seccomp_data& data, void* aux) { diff --git a/sandbox/linux/bpf_dsl/seccomp_macros.h b/sandbox/linux/bpf_dsl/seccomp_macros.h index 7fd0e67..b72357a 100644 --- a/sandbox/linux/bpf_dsl/seccomp_macros.h +++ b/sandbox/linux/bpf_dsl/seccomp_macros.h @@ -21,8 +21,6 @@ #endif #endif -#include "sandbox/linux/system_headers/linux_seccomp.h" // For AUDIT_ARCH_* - // Impose some reasonable maximum BPF program size. Realistically, the // kernel probably has much lower limits. But by limiting to less than // 30 bits, we can ease requirements on some of our data types. diff --git a/sandbox/linux/bpf_dsl/trap_registry.h b/sandbox/linux/bpf_dsl/trap_registry.h index 0a5d2f1..432290b 100644 --- a/sandbox/linux/bpf_dsl/trap_registry.h +++ b/sandbox/linux/bpf_dsl/trap_registry.h @@ -58,10 +58,6 @@ class SANDBOX_EXPORT TrapRegistry { protected: TrapRegistry() {} - - // TrapRegistry's destructor is intentionally non-virtual so that - // implementations can omit their destructor. Instead we protect against - // misuse by marking it protected. ~TrapRegistry() {} DISALLOW_COPY_AND_ASSIGN(TrapRegistry); diff --git a/sandbox/linux/seccomp-bpf/trap.h b/sandbox/linux/seccomp-bpf/trap.h index 4073bfe..63fff88 100644 --- a/sandbox/linux/seccomp-bpf/trap.h +++ b/sandbox/linux/seccomp-bpf/trap.h @@ -53,9 +53,9 @@ class SANDBOX_EXPORT Trap : public bpf_dsl::TrapRegistry { // automatically as needed. Trap(); - // The destructor is unimplemented as destroying this object would - // break subsequent system calls that trigger a SIGSYS. - ~Trap() = delete; + // The destructor is unimplemented. Don't ever attempt to destruct this + // object. It'll break subsequent system calls that trigger a SIGSYS. + ~Trap(); static void SigSysAction(int nr, siginfo_t* info, void* void_context); diff --git a/sandbox/linux/seccomp-bpf/verifier.h b/sandbox/linux/seccomp-bpf/verifier.h index 50efe64..6bd747bd 100644 --- a/sandbox/linux/seccomp-bpf/verifier.h +++ b/sandbox/linux/seccomp-bpf/verifier.h @@ -10,7 +10,6 @@ #include <vector> #include "base/macros.h" -#include "sandbox/sandbox_export.h" struct sock_filter; @@ -21,7 +20,7 @@ class Policy; class PolicyCompiler; } -class SANDBOX_EXPORT Verifier { +class Verifier { public: // Evaluate the BPF program for all possible inputs and verify that it // computes the correct result. We use the "evaluators" to determine |