Index: sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc |
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc |
index b5bfd357a34cc592589d6bc5fc38c6fe02d7b4cf..8342e699671a4876fc4102e6cce2f0329eeb246a 100644 |
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc |
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc |
@@ -126,43 +126,52 @@ SANDBOX_TEST(SandboxBPF, DISABLE_ON_TSAN(VerboseAPITesting)) { |
// A simple blacklist test |
-ErrorCode BlacklistNanosleepPolicy(SandboxBPF*, int sysno, void* aux) { |
- // Since no type was specified in BPF_TEST as a fourth argument, |
- // |aux| must be NULL here. |
- BPF_ASSERT(NULL == aux); |
- if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
- // FIXME: we should really not have to do that in a trivial policy |
- return ErrorCode(ENOSYS); |
+class BlacklistNanosleepPolicy : public SandboxBPFPolicy { |
+ public: |
+ BlacklistNanosleepPolicy() {} |
+ virtual ErrorCode EvaluateSyscall(SandboxBPF*, int sysno) const OVERRIDE { |
+ DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
+ switch (sysno) { |
+ case __NR_nanosleep: |
+ return ErrorCode(EACCES); |
+ default: |
+ return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ } |
} |
- switch (sysno) { |
- case __NR_nanosleep: |
- return ErrorCode(EACCES); |
- default: |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
- } |
-} |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(BlacklistNanosleepPolicy); |
+}; |
-BPF_TEST(SandboxBPF, ApplyBasicBlacklistPolicy, BlacklistNanosleepPolicy) { |
+BPF_TEST_C(SandboxBPF, ApplyBasicBlacklistPolicy, BlacklistNanosleepPolicy) { |
// nanosleep() should be denied |
const struct timespec ts = {0, 0}; |
errno = 0; |
BPF_ASSERT(syscall(__NR_nanosleep, &ts, NULL) == -1); |
BPF_ASSERT(errno == EACCES); |
} |
+ |
// Now do a simple whitelist test |
-ErrorCode WhitelistGetpidPolicy(SandboxBPF*, int sysno, void*) { |
- switch (sysno) { |
- case __NR_getpid: |
- case __NR_exit_group: |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
- default: |
- return ErrorCode(ENOMEM); |
+class WhitelistGetpidPolicy : public SandboxBPFPolicy { |
+ public: |
+ WhitelistGetpidPolicy() {} |
+ virtual ErrorCode EvaluateSyscall(SandboxBPF*, int sysno) const OVERRIDE { |
+ DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
+ switch (sysno) { |
+ case __NR_getpid: |
+ case __NR_exit_group: |
+ return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ default: |
+ return ErrorCode(ENOMEM); |
+ } |
} |
-} |
-BPF_TEST(SandboxBPF, ApplyBasicWhitelistPolicy, WhitelistGetpidPolicy) { |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(WhitelistGetpidPolicy); |
+}; |
+ |
+BPF_TEST_C(SandboxBPF, ApplyBasicWhitelistPolicy, WhitelistGetpidPolicy) { |
// getpid() should be allowed |
errno = 0; |
BPF_ASSERT(syscall(__NR_getpid) > 0); |
@@ -184,11 +193,7 @@ intptr_t EnomemHandler(const struct arch_seccomp_data& args, void* aux) { |
ErrorCode BlacklistNanosleepPolicySigsys(SandboxBPF* sandbox, |
int sysno, |
int* aux) { |
- if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
- // FIXME: we should really not have to do that in a trivial policy |
- return ErrorCode(ENOSYS); |
- } |
- |
+ DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
switch (sysno) { |
case __NR_nanosleep: |
return sandbox->Trap(EnomemHandler, aux); |
@@ -218,12 +223,17 @@ BPF_TEST(SandboxBPF, |
// A simple test that verifies we can return arbitrary errno values. |
-ErrorCode ErrnoTestPolicy(SandboxBPF*, int sysno, void*) { |
- if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
- // FIXME: we should really not have to do that in a trivial policy |
- return ErrorCode(ENOSYS); |
- } |
+class ErrnoTestPolicy : public SandboxBPFPolicy { |
+ public: |
+ ErrnoTestPolicy() {} |
+ virtual ErrorCode EvaluateSyscall(SandboxBPF*, int sysno) const OVERRIDE; |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(ErrnoTestPolicy); |
+}; |
+ |
+ErrorCode ErrnoTestPolicy::EvaluateSyscall(SandboxBPF*, int sysno) const { |
+ DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
switch (sysno) { |
#if defined(ANDROID) |
case __NR_dup3: // dup2 is a wrapper of dup3 in android |
@@ -252,7 +262,7 @@ ErrorCode ErrnoTestPolicy(SandboxBPF*, int sysno, void*) { |
} |
} |
-BPF_TEST(SandboxBPF, ErrnoTest, ErrnoTestPolicy) { |
+BPF_TEST_C(SandboxBPF, ErrnoTest, ErrnoTestPolicy) { |
// Verify that dup2() returns success, but doesn't actually run. |
int fds[4]; |
BPF_ASSERT(pipe(fds) == 0); |
@@ -377,22 +387,24 @@ int SysnoToRandomErrno(int sysno) { |
return ((sysno & ~3) >> 2) % 29 + 1; |
} |
-ErrorCode SyntheticPolicy(SandboxBPF*, int sysno, void*) { |
- if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
- // FIXME: we should really not have to do that in a trivial policy |
- return ErrorCode(ENOSYS); |
- } |
- |
- if (sysno == __NR_exit_group || sysno == __NR_write) { |
- // exit_group() is special, we really need it to work. |
- // write() is needed for BPF_ASSERT() to report a useful error message. |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
- } else { |
+class SyntheticPolicy : public SandboxBPFPolicy { |
+ public: |
+ SyntheticPolicy() {} |
+ virtual ErrorCode EvaluateSyscall(SandboxBPF*, int sysno) const OVERRIDE { |
+ DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
+ if (sysno == __NR_exit_group || sysno == __NR_write) { |
+ // exit_group() is special, we really need it to work. |
+ // write() is needed for BPF_ASSERT() to report a useful error message. |
+ return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ } |
return ErrorCode(SysnoToRandomErrno(sysno)); |
} |
-} |
-BPF_TEST(SandboxBPF, SyntheticPolicy, SyntheticPolicy) { |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(SyntheticPolicy); |
+}; |
+ |
+BPF_TEST_C(SandboxBPF, SyntheticPolicy, SyntheticPolicy) { |
// Ensure that that kExpectedReturnValue + syscallnumber + 1 does not int |
// overflow. |
BPF_ASSERT(std::numeric_limits<int>::max() - kExpectedReturnValue - 1 >= |
@@ -426,23 +438,25 @@ int ArmPrivateSysnoToErrno(int sysno) { |
} |
} |
-ErrorCode ArmPrivatePolicy(SandboxBPF*, int sysno, void*) { |
- if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
- // FIXME: we should really not have to do that in a trivial policy. |
- return ErrorCode(ENOSYS); |
- } |
- |
- // Start from |__ARM_NR_set_tls + 1| so as not to mess with actual |
- // ARM private system calls. |
- if (sysno >= static_cast<int>(__ARM_NR_set_tls + 1) && |
- sysno <= static_cast<int>(MAX_PRIVATE_SYSCALL)) { |
- return ErrorCode(ArmPrivateSysnoToErrno(sysno)); |
- } else { |
+class ArmPrivatePolicy : public SandboxBPFPolicy { |
+ public: |
+ ArmPrivatePolicy() {} |
+ virtual ErrorCode EvaluateSyscall(SandboxBPF*, int sysno) const OVERRIDE { |
+ DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
+ // Start from |__ARM_NR_set_tls + 1| so as not to mess with actual |
+ // ARM private system calls. |
+ if (sysno >= static_cast<int>(__ARM_NR_set_tls + 1) && |
+ sysno <= static_cast<int>(MAX_PRIVATE_SYSCALL)) { |
+ return ErrorCode(ArmPrivateSysnoToErrno(sysno)); |
+ } |
return ErrorCode(ErrorCode::ERR_ALLOWED); |
} |
-} |
-BPF_TEST(SandboxBPF, ArmPrivatePolicy, ArmPrivatePolicy) { |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(ArmPrivatePolicy); |
+}; |
+ |
+BPF_TEST_C(SandboxBPF, ArmPrivatePolicy, ArmPrivatePolicy) { |
for (int syscall_number = static_cast<int>(__ARM_NR_set_tls + 1); |
syscall_number <= static_cast<int>(MAX_PRIVATE_SYSCALL); |
++syscall_number) { |
@@ -539,22 +553,29 @@ intptr_t PrctlHandler(const struct arch_seccomp_data& args, void*) { |
} |
} |
-ErrorCode PrctlPolicy(SandboxBPF* sandbox, int sysno, void* aux) { |
- setenv(kSandboxDebuggingEnv, "t", 0); |
- Die::SuppressInfoMessages(true); |
+class PrctlPolicy : public SandboxBPFPolicy { |
+ public: |
+ PrctlPolicy() {} |
+ virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
+ int sysno) const OVERRIDE { |
+ DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
+ setenv(kSandboxDebuggingEnv, "t", 0); |
+ Die::SuppressInfoMessages(true); |
+ |
+ if (sysno == __NR_prctl) { |
+ // Handle prctl() inside an UnsafeTrap() |
+ return sandbox->UnsafeTrap(PrctlHandler, NULL); |
+ } |
- if (sysno == __NR_prctl) { |
- // Handle prctl() inside an UnsafeTrap() |
- return sandbox->UnsafeTrap(PrctlHandler, NULL); |
- } else if (SandboxBPF::IsValidSyscallNumber(sysno)) { |
// Allow all other system calls. |
return ErrorCode(ErrorCode::ERR_ALLOWED); |
- } else { |
- return ErrorCode(ENOSYS); |
} |
-} |
-BPF_TEST(SandboxBPF, ForwardSyscall, PrctlPolicy) { |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(PrctlPolicy); |
+}; |
+ |
+BPF_TEST_C(SandboxBPF, ForwardSyscall, PrctlPolicy) { |
// This call should never be allowed. But our policy will intercept it and |
// let it pass successfully. |
BPF_ASSERT( |
@@ -585,7 +606,19 @@ intptr_t AllowRedirectedSyscall(const struct arch_seccomp_data& args, void*) { |
return SandboxBPF::ForwardSyscall(args); |
} |
-ErrorCode RedirectAllSyscallsPolicy(SandboxBPF* sandbox, int sysno, void* aux) { |
+class RedirectAllSyscallsPolicy : public SandboxBPFPolicy { |
+ public: |
+ RedirectAllSyscallsPolicy() {} |
+ virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
+ int sysno) const OVERRIDE; |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(RedirectAllSyscallsPolicy); |
+}; |
+ |
+ErrorCode RedirectAllSyscallsPolicy::EvaluateSyscall(SandboxBPF* sandbox, |
+ int sysno) const { |
+ DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
setenv(kSandboxDebuggingEnv, "t", 0); |
Die::SuppressInfoMessages(true); |
@@ -602,11 +635,8 @@ ErrorCode RedirectAllSyscallsPolicy(SandboxBPF* sandbox, int sysno, void* aux) { |
#endif |
) { |
return ErrorCode(ErrorCode::ERR_ALLOWED); |
- } else if (SandboxBPF::IsValidSyscallNumber(sysno)) { |
- return sandbox->UnsafeTrap(AllowRedirectedSyscall, aux); |
- } else { |
- return ErrorCode(ENOSYS); |
} |
+ return sandbox->UnsafeTrap(AllowRedirectedSyscall, NULL); |
} |
int bus_handler_fd_ = -1; |
@@ -615,7 +645,7 @@ void SigBusHandler(int, siginfo_t* info, void* void_context) { |
BPF_ASSERT(write(bus_handler_fd_, "\x55", 1) == 1); |
} |
-BPF_TEST(SandboxBPF, SigBus, RedirectAllSyscallsPolicy) { |
+BPF_TEST_C(SandboxBPF, SigBus, RedirectAllSyscallsPolicy) { |
// We use the SIGBUS bit in the signal mask as a thread-local boolean |
// value in the implementation of UnsafeTrap(). This is obviously a bit |
// of a hack that could conceivably interfere with code that uses SIGBUS |
@@ -638,7 +668,7 @@ BPF_TEST(SandboxBPF, SigBus, RedirectAllSyscallsPolicy) { |
BPF_ASSERT(c == 0x55); |
} |
-BPF_TEST(SandboxBPF, SigMask, RedirectAllSyscallsPolicy) { |
+BPF_TEST_C(SandboxBPF, SigMask, RedirectAllSyscallsPolicy) { |
// Signal masks are potentially tricky to handle. For instance, if we |
// ever tried to update them from inside a Trap() or UnsafeTrap() handler, |
// the call to sigreturn() at the end of the signal handler would undo |
@@ -665,7 +695,7 @@ BPF_TEST(SandboxBPF, SigMask, RedirectAllSyscallsPolicy) { |
BPF_ASSERT(sigismember(&mask2, SIGUSR2)); |
} |
-BPF_TEST(SandboxBPF, UnsafeTrapWithErrno, RedirectAllSyscallsPolicy) { |
+BPF_TEST_C(SandboxBPF, UnsafeTrapWithErrno, RedirectAllSyscallsPolicy) { |
// An UnsafeTrap() (or for that matter, a Trap()) has to report error |
// conditions by returning an exit code in the range -1..-4096. This |
// should happen automatically if using ForwardSyscall(). If the TrapFnc() |
@@ -819,11 +849,19 @@ BPF_TEST(SandboxBPF, |
// Simple test demonstrating how to use SandboxBPF::Cond() |
-ErrorCode SimpleCondTestPolicy(SandboxBPF* sandbox, int sysno, void*) { |
- if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
- // FIXME: we should really not have to do that in a trivial policy |
- return ErrorCode(ENOSYS); |
- } |
+class SimpleCondTestPolicy : public SandboxBPFPolicy { |
+ public: |
+ SimpleCondTestPolicy() {} |
+ virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
+ int sysno) const OVERRIDE; |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(SimpleCondTestPolicy); |
+}; |
+ |
+ErrorCode SimpleCondTestPolicy::EvaluateSyscall(SandboxBPF* sandbox, |
+ int sysno) const { |
+ DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
// We deliberately return unusual errno values upon failure, so that we |
// can uniquely test for these values. In a "real" policy, you would want |
@@ -869,7 +907,7 @@ ErrorCode SimpleCondTestPolicy(SandboxBPF* sandbox, int sysno, void*) { |
} |
} |
-BPF_TEST(SandboxBPF, SimpleCondTest, SimpleCondTestPolicy) { |
+BPF_TEST_C(SandboxBPF, SimpleCondTest, SimpleCondTestPolicy) { |
int fd; |
BPF_ASSERT((fd = open("/proc/self/comm", O_RDWR)) == -1); |
BPF_ASSERT(errno == EROFS); |
@@ -1198,11 +1236,20 @@ BPF_TEST(SandboxBPF, |
BPF_AUX->VerifyFilter(); |
} |
-ErrorCode EqualityArgumentWidthPolicy(SandboxBPF* sandbox, int sysno, void*) { |
- if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
- // FIXME: we should really not have to do that in a trivial policy |
- return ErrorCode(ENOSYS); |
- } else if (sysno == __NR_uname) { |
+class EqualityArgumentWidthPolicy : public SandboxBPFPolicy { |
+ public: |
+ EqualityArgumentWidthPolicy() {} |
+ virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
+ int sysno) const OVERRIDE; |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(EqualityArgumentWidthPolicy); |
+}; |
+ |
+ErrorCode EqualityArgumentWidthPolicy::EvaluateSyscall(SandboxBPF* sandbox, |
+ int sysno) const { |
+ DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
+ if (sysno == __NR_uname) { |
return sandbox->Cond( |
0, |
ErrorCode::TP_32BIT, |
@@ -1228,12 +1275,11 @@ ErrorCode EqualityArgumentWidthPolicy(SandboxBPF* sandbox, int sysno, void*) { |
0x55555555AAAAAAAAULL, |
ErrorCode(1), |
ErrorCode(2))); |
- } else { |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
} |
+ return ErrorCode(ErrorCode::ERR_ALLOWED); |
} |
-BPF_TEST(SandboxBPF, EqualityArgumentWidth, EqualityArgumentWidthPolicy) { |
+BPF_TEST_C(SandboxBPF, EqualityArgumentWidth, EqualityArgumentWidthPolicy) { |
BPF_ASSERT(SandboxSyscall(__NR_uname, 0, 0x55555555) == -1); |
BPF_ASSERT(SandboxSyscall(__NR_uname, 0, 0xAAAAAAAA) == -2); |
#if __SIZEOF_POINTER__ > 4 |
@@ -1253,62 +1299,74 @@ BPF_TEST(SandboxBPF, EqualityArgumentWidth, EqualityArgumentWidthPolicy) { |
// On 32bit machines, there is no way to pass a 64bit argument through the |
// syscall interface. So, we have to skip the part of the test that requires |
// 64bit arguments. |
-BPF_DEATH_TEST(SandboxBPF, |
- EqualityArgumentUnallowed64bit, |
- DEATH_MESSAGE("Unexpected 64bit argument detected"), |
- EqualityArgumentWidthPolicy) { |
+BPF_DEATH_TEST_C(SandboxBPF, |
+ EqualityArgumentUnallowed64bit, |
+ DEATH_MESSAGE("Unexpected 64bit argument detected"), |
+ EqualityArgumentWidthPolicy) { |
SandboxSyscall(__NR_uname, 0, 0x5555555555555555ULL); |
} |
#endif |
-ErrorCode EqualityWithNegativeArgumentsPolicy(SandboxBPF* sandbox, |
- int sysno, |
- void*) { |
- if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
- // FIXME: we should really not have to do that in a trivial policy |
- return ErrorCode(ENOSYS); |
- } else if (sysno == __NR_uname) { |
- return sandbox->Cond(0, |
- ErrorCode::TP_32BIT, |
- ErrorCode::OP_EQUAL, |
- 0xFFFFFFFF, |
- ErrorCode(1), |
- ErrorCode(2)); |
- } else { |
+class EqualityWithNegativeArgumentsPolicy : public SandboxBPFPolicy { |
+ public: |
+ EqualityWithNegativeArgumentsPolicy() {} |
+ virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
+ int sysno) const OVERRIDE { |
+ DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
+ if (sysno == __NR_uname) { |
+ return sandbox->Cond(0, |
+ ErrorCode::TP_32BIT, |
+ ErrorCode::OP_EQUAL, |
+ 0xFFFFFFFF, |
+ ErrorCode(1), |
+ ErrorCode(2)); |
+ } |
return ErrorCode(ErrorCode::ERR_ALLOWED); |
} |
-} |
-BPF_TEST(SandboxBPF, |
- EqualityWithNegativeArguments, |
- EqualityWithNegativeArgumentsPolicy) { |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(EqualityWithNegativeArgumentsPolicy); |
+}; |
+ |
+BPF_TEST_C(SandboxBPF, |
+ EqualityWithNegativeArguments, |
+ EqualityWithNegativeArgumentsPolicy) { |
BPF_ASSERT(SandboxSyscall(__NR_uname, 0xFFFFFFFF) == -1); |
BPF_ASSERT(SandboxSyscall(__NR_uname, -1) == -1); |
BPF_ASSERT(SandboxSyscall(__NR_uname, -1LL) == -1); |
} |
#if __SIZEOF_POINTER__ > 4 |
-BPF_DEATH_TEST(SandboxBPF, |
- EqualityWithNegative64bitArguments, |
- DEATH_MESSAGE("Unexpected 64bit argument detected"), |
- EqualityWithNegativeArgumentsPolicy) { |
+BPF_DEATH_TEST_C(SandboxBPF, |
+ EqualityWithNegative64bitArguments, |
+ DEATH_MESSAGE("Unexpected 64bit argument detected"), |
+ EqualityWithNegativeArgumentsPolicy) { |
// When expecting a 32bit system call argument, we look at the MSB of the |
// 64bit value and allow both "0" and "-1". But the latter is allowed only |
// iff the LSB was negative. So, this death test should error out. |
BPF_ASSERT(SandboxSyscall(__NR_uname, 0xFFFFFFFF00000000LL) == -1); |
} |
#endif |
-ErrorCode AllBitTestPolicy(SandboxBPF* sandbox, int sysno, void *) { |
+class AllBitTestPolicy : public SandboxBPFPolicy { |
+ public: |
+ AllBitTestPolicy() {} |
+ virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
+ int sysno) const OVERRIDE; |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(AllBitTestPolicy); |
+}; |
+ |
+ErrorCode AllBitTestPolicy::EvaluateSyscall(SandboxBPF* sandbox, |
+ int sysno) const { |
+ DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
// Test the OP_HAS_ALL_BITS conditional test operator with a couple of |
// different bitmasks. We try to find bitmasks that could conceivably |
// touch corner cases. |
// For all of these tests, we override the uname(). We can make use with |
// a single system call number, as we use the first system call argument to |
// select the different bit masks that we want to test against. |
- if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
- // FIXME: we should really not have to do that in a trivial policy |
- return ErrorCode(ENOSYS); |
- } else if (sysno == __NR_uname) { |
+ if (sysno == __NR_uname) { |
return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 0, |
sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ALL_BITS, |
0x0, |
@@ -1364,9 +1422,8 @@ ErrorCode AllBitTestPolicy(SandboxBPF* sandbox, int sysno, void *) { |
ErrorCode(1), ErrorCode(0)), |
sandbox->Kill("Invalid test case number")))))))))))); |
- } else { |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
} |
+ return ErrorCode(ErrorCode::ERR_ALLOWED); |
} |
// Define a macro that performs tests using our test policy. |
@@ -1391,7 +1448,7 @@ ErrorCode AllBitTestPolicy(SandboxBPF* sandbox, int sysno, void *) { |
// We expect these tests to succeed on 64bit systems, but to tail on 32bit |
// systems. |
#define EXPT64_SUCCESS (sizeof(void*) > 4 ? EXPECT_SUCCESS : EXPECT_FAILURE) |
-BPF_TEST(SandboxBPF, AllBitTests, AllBitTestPolicy) { |
+BPF_TEST_C(SandboxBPF, AllBitTests, AllBitTestPolicy) { |
// 32bit test: all of 0x0 (should always be true) |
BITMASK_TEST( 0, 0, ALLBITS32, 0, EXPECT_SUCCESS); |
BITMASK_TEST( 0, 1, ALLBITS32, 0, EXPECT_SUCCESS); |
@@ -1494,17 +1551,26 @@ BPF_TEST(SandboxBPF, AllBitTests, AllBitTestPolicy) { |
BITMASK_TEST(10, -1L, ALLBITS64,0x100000001, EXPT64_SUCCESS); |
} |
-ErrorCode AnyBitTestPolicy(SandboxBPF* sandbox, int sysno, void*) { |
+class AnyBitTestPolicy : public SandboxBPFPolicy { |
+ public: |
+ AnyBitTestPolicy() {} |
+ virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
+ int sysno) const OVERRIDE; |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(AnyBitTestPolicy); |
+}; |
+ |
+ErrorCode AnyBitTestPolicy::EvaluateSyscall(SandboxBPF* sandbox, |
+ int sysno) const { |
+ DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
// Test the OP_HAS_ANY_BITS conditional test operator with a couple of |
// different bitmasks. We try to find bitmasks that could conceivably |
// touch corner cases. |
// For all of these tests, we override the uname(). We can make use with |
// a single system call number, as we use the first system call argument to |
// select the different bit masks that we want to test against. |
- if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
- // FIXME: we should really not have to do that in a trivial policy |
- return ErrorCode(ENOSYS); |
- } else if (sysno == __NR_uname) { |
+ if (sysno == __NR_uname) { |
return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 0, |
sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, |
0x0, |
@@ -1563,12 +1629,11 @@ ErrorCode AnyBitTestPolicy(SandboxBPF* sandbox, int sysno, void*) { |
ErrorCode(1), ErrorCode(0)), |
sandbox->Kill("Invalid test case number")))))))))))); |
- } else { |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
} |
+ return ErrorCode(ErrorCode::ERR_ALLOWED); |
} |
-BPF_TEST(SandboxBPF, AnyBitTests, AnyBitTestPolicy) { |
+BPF_TEST_C(SandboxBPF, AnyBitTests, AnyBitTestPolicy) { |
// 32bit test: any of 0x0 (should always be false) |
BITMASK_TEST( 0, 0, ANYBITS32, 0x0, EXPECT_FAILURE); |
BITMASK_TEST( 0, 1, ANYBITS32, 0x0, EXPECT_FAILURE); |
@@ -1698,15 +1763,25 @@ intptr_t PthreadTrapHandler(const struct arch_seccomp_data& args, void* aux) { |
} |
return -EPERM; |
} |
-ErrorCode PthreadPolicyEquality(SandboxBPF* sandbox, int sysno, void* aux) { |
+ |
+class PthreadPolicyEquality : public SandboxBPFPolicy { |
+ public: |
+ PthreadPolicyEquality() {} |
+ virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
+ int sysno) const OVERRIDE; |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(PthreadPolicyEquality); |
+}; |
+ |
+ErrorCode PthreadPolicyEquality::EvaluateSyscall(SandboxBPF* sandbox, |
+ int sysno) const { |
+ DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
// This policy allows creating threads with pthread_create(). But it |
// doesn't allow any other uses of clone(). Most notably, it does not |
// allow callers to implement fork() or vfork() by passing suitable flags |
// to the clone() system call. |
- if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
- // FIXME: we should really not have to do that in a trivial policy |
- return ErrorCode(ENOSYS); |
- } else if (sysno == __NR_clone) { |
+ if (sysno == __NR_clone) { |
// We have seen two different valid combinations of flags. Glibc |
// uses the more modern flags, sets the TLS from the call to clone(), and |
// uses futexes to monitor threads. Android's C run-time library, doesn't |
@@ -1733,20 +1808,28 @@ ErrorCode PthreadPolicyEquality(SandboxBPF* sandbox, int sysno, void* aux) { |
kBaseAndroidCloneMask, |
ErrorCode(ErrorCode::ERR_ALLOWED), |
sandbox->Trap(PthreadTrapHandler, "Unknown mask")))); |
- } else { |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
} |
+ return ErrorCode(ErrorCode::ERR_ALLOWED); |
} |
-ErrorCode PthreadPolicyBitMask(SandboxBPF* sandbox, int sysno, void* aux) { |
+class PthreadPolicyBitMask : public SandboxBPFPolicy { |
+ public: |
+ PthreadPolicyBitMask() {} |
+ virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
+ int sysno) const OVERRIDE; |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(PthreadPolicyBitMask); |
+}; |
+ |
+ErrorCode PthreadPolicyBitMask::EvaluateSyscall(SandboxBPF* sandbox, |
+ int sysno) const { |
+ DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
// This policy allows creating threads with pthread_create(). But it |
// doesn't allow any other uses of clone(). Most notably, it does not |
// allow callers to implement fork() or vfork() by passing suitable flags |
// to the clone() system call. |
- if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
- // FIXME: we should really not have to do that in a trivial policy |
- return ErrorCode(ENOSYS); |
- } else if (sysno == __NR_clone) { |
+ if (sysno == __NR_clone) { |
// We have seen two different valid combinations of flags. Glibc |
// uses the more modern flags, sets the TLS from the call to clone(), and |
// uses futexes to monitor threads. Android's C run-time library, doesn't |
@@ -1778,9 +1861,8 @@ ErrorCode PthreadPolicyBitMask(SandboxBPF* sandbox, int sysno, void* aux) { |
sandbox->Trap(PthreadTrapHandler, |
"Missing mandatory CLONE_XXX flags " |
"when creating new thread"))); |
- } else { |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
} |
+ return ErrorCode(ErrorCode::ERR_ALLOWED); |
} |
static void* ThreadFnc(void* arg) { |
@@ -1822,9 +1904,13 @@ static void PthreadTest() { |
&pid) == -EPERM); |
} |
-BPF_TEST(SandboxBPF, PthreadEquality, PthreadPolicyEquality) { PthreadTest(); } |
+BPF_TEST_C(SandboxBPF, PthreadEquality, PthreadPolicyEquality) { |
+ PthreadTest(); |
+} |
-BPF_TEST(SandboxBPF, PthreadBitMask, PthreadPolicyBitMask) { PthreadTest(); } |
+BPF_TEST_C(SandboxBPF, PthreadBitMask, PthreadPolicyBitMask) { |
+ PthreadTest(); |
+} |
} // namespace |