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 54fe7a7bff7bec3748b7a3a4c54eddb007724f07..19c64a9bd2983591a2e2d08fd80bdf2841ca47a1 100644 |
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc |
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc |
@@ -4,7 +4,7 @@ |
#include <ostream> |
-#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" |
+#include "sandbox/linux/seccomp-bpf/bpf_tests.h" |
#include "sandbox/linux/seccomp-bpf/verifier.h" |
#include "testing/gtest/include/gtest/gtest.h" |
@@ -17,6 +17,8 @@ const int kExpectedReturnValue = 42; |
const int kArmPublicSysnoCeiling = __NR_SYSCALL_BASE + 1024; |
#endif |
+// This test should execute no matter whether we have kernel support. So, |
+// we make it a TEST() instead of a BPF_TEST(). |
TEST(SandboxBpf, CallSupports) { |
// We check that we don't crash, but it's ok if the kernel doesn't |
// support it. |
@@ -31,9 +33,10 @@ TEST(SandboxBpf, CallSupports) { |
<< "\n"; |
} |
-TEST(SandboxBpf, CallSupportsTwice) { |
+BPF_TEST(SandboxBpf, CallSupportsTwice) { |
Sandbox::supportsSeccompSandbox(-1); |
Sandbox::supportsSeccompSandbox(-1); |
+ return true; |
} |
__attribute__((noreturn)) void DoCrash() { |
@@ -63,50 +66,20 @@ __attribute__((noreturn)) void ExitGroup(int status) { |
// Helper function to start a sandbox with a policy specified in |
// evaluator |
void StartSandboxOrDie(Sandbox::EvaluateSyscall evaluator) { |
- int proc_fd = open("/proc", O_RDONLY|O_DIRECTORY); |
- if (proc_fd < 0 || !evaluator) { |
- ExitGroup(1); |
- } |
- if (Sandbox::supportsSeccompSandbox(proc_fd) != |
- Sandbox::STATUS_AVAILABLE) { |
- ExitGroup(1); |
- } |
+ BPF_ASSERT(evaluator); |
+ |
+ // Ensure the the sandbox is actually available at this time |
+ int proc_fd; |
+ BPF_ASSERT((proc_fd = open("/proc", O_RDONLY|O_DIRECTORY)) >= 0); |
+ BPF_ASSERT(Sandbox::supportsSeccompSandbox(proc_fd) == |
+ Sandbox::STATUS_AVAILABLE); |
+ |
+ // Initialize and then start the sandbox with our custom policy |
Sandbox::setProcFd(proc_fd); |
Sandbox::setSandboxPolicy(evaluator, NULL); |
Sandbox::startSandbox(); |
} |
-void RunInSandbox(Sandbox::EvaluateSyscall evaluator, |
- void (*SandboxedCode)()) { |
- // TODO(markus): Implement IsEqual for ErrorCode |
- // IsEqual(evaluator(__NR_exit_group), Sandbox::SB_ALLOWED) << |
- // "You need to always allow exit_group() in your test policy"; |
- StartSandboxOrDie(evaluator); |
- // TODO(jln): find a way to use the testing framework inside |
- // SandboxedCode() or at the very least to surface errors |
- SandboxedCode(); |
- // SandboxedCode() should have exited, this is a failure |
- ExitGroup(1); |
-} |
- |
-// evaluator should always allow ExitGroup |
-// SandboxedCode should ExitGroup(kExpectedReturnValue) if and only if |
-// things go as expected. |
-void TryPolicyInProcess(Sandbox::EvaluateSyscall evaluator, |
- void (*SandboxedCode)()) { |
- // TODO(jln) figure out a way to surface whether we're actually testing |
- // something or not. |
- if (Sandbox::supportsSeccompSandbox(-1) == Sandbox::STATUS_AVAILABLE) { |
- EXPECT_EXIT(RunInSandbox(evaluator, SandboxedCode), |
- ::testing::ExitedWithCode(kExpectedReturnValue), |
- ""); |
- } else { |
- // The sandbox is not available. We should still try to exercise what we |
- // can. |
- // TODO(markus): (crbug.com/141545) let us call the compiler from here. |
- Sandbox::setSandboxPolicy(evaluator, NULL); |
- } |
-} |
// A simple blacklist test |
@@ -124,17 +97,16 @@ Sandbox::ErrorCode BlacklistNanosleepPolicy(int sysno) { |
} |
} |
-void NanosleepProcess(void) { |
+BPF_TEST(SandboxBpf, ApplyBasicBlacklistPolicy) { |
+ StartSandboxOrDie(BlacklistNanosleepPolicy); |
+ |
+ // nanosleep() should be denied |
const struct timespec ts = {0, 0}; |
errno = 0; |
- if(syscall(__NR_nanosleep, &ts, NULL) != -1 || errno != EACCES) { |
- ExitGroup(1); |
- } |
- ExitGroup(kExpectedReturnValue); |
-} |
+ BPF_ASSERT(syscall(__NR_nanosleep, &ts, NULL) == -1); |
+ BPF_ASSERT(errno == EACCES); |
-TEST(SandboxBpf, ApplyBasicBlacklistPolicy) { |
- TryPolicyInProcess(BlacklistNanosleepPolicy, NanosleepProcess); |
+ return true; |
} |
// Now do a simple whitelist test |
@@ -149,19 +121,19 @@ Sandbox::ErrorCode WhitelistGetpidPolicy(int sysno) { |
} |
} |
-void GetpidProcess(void) { |
- errno = 0; |
+BPF_TEST(SandboxBpf, ApplyBasicWhitelistPolicy) { |
+ StartSandboxOrDie(WhitelistGetpidPolicy); |
+ |
// getpid() should be allowed |
- if (syscall(__NR_getpid) < 0 || errno) |
- ExitGroup(1); |
+ errno = 0; |
+ BPF_ASSERT(syscall(__NR_getpid) > 0); |
+ BPF_ASSERT(errno == 0); |
+ |
// getpgid() should be denied |
- if (getpgid(0) != -1 || errno != ENOMEM) |
- ExitGroup(1); |
- ExitGroup(kExpectedReturnValue); |
-} |
+ BPF_ASSERT(getpgid(0) == -1); |
+ BPF_ASSERT(errno == ENOMEM); |
-TEST(SandboxBpf, ApplyBasicWhitelistPolicy) { |
- TryPolicyInProcess(WhitelistGetpidPolicy, GetpidProcess); |
+ return true; |
} |
// A simple blacklist policy, with a SIGSYS handler |
@@ -194,26 +166,25 @@ Sandbox::ErrorCode BlacklistNanosleepPolicySigsys(int sysno) { |
} |
} |
-void NanosleepProcessSigsys(void) { |
- const struct timespec ts = {0, 0}; |
- errno = 0; |
+BPF_TEST(SandboxBpf, BasicBlacklistWithSigsys) { |
+ StartSandboxOrDie(BlacklistNanosleepPolicySigsys); |
+ |
// getpid() should work properly |
- if (syscall(__NR_getpid) < 0) |
- ExitGroup(1); |
+ errno = 0; |
+ BPF_ASSERT(syscall(__NR_getpid) > 0); |
+ BPF_ASSERT(errno == 0); |
+ |
// Our Auxiliary Data, should be reset by the signal handler |
BlacklistNanosleepPolicySigsysAuxData = -1; |
- errno = 0; |
- if (syscall(__NR_nanosleep, &ts, NULL) != -1 || errno != ENOMEM) |
- ExitGroup(1); |
+ const struct timespec ts = {0, 0}; |
+ BPF_ASSERT(syscall(__NR_nanosleep, &ts, NULL) == -1); |
+ BPF_ASSERT(errno == ENOMEM); |
+ |
// We expect the signal handler to modify AuxData |
- if (BlacklistNanosleepPolicySigsysAuxData != kExpectedReturnValue) |
- ExitGroup(1); |
- else |
- ExitGroup(kExpectedReturnValue); |
-} |
+ BPF_ASSERT( |
+ BlacklistNanosleepPolicySigsysAuxData == kExpectedReturnValue); |
-TEST(SandboxBpf, BasicBlacklistWithSigsys) { |
- TryPolicyInProcess(BlacklistNanosleepPolicySigsys, NanosleepProcessSigsys); |
+ return true; |
} |
// A more complex, but synthetic policy. This tests the correctness of the BPF |
@@ -252,13 +223,14 @@ Sandbox::ErrorCode SyntheticPolicy(int sysno) { |
} |
} |
-void SyntheticProcess(void) { |
+BPF_TEST(SandboxBpf, SyntheticPolicy) { |
// Ensure that that kExpectedReturnValue + syscallnumber + 1 does not int |
// overflow. |
- if (std::numeric_limits<int>::max() - kExpectedReturnValue - 1 < |
- static_cast<int>(MAX_SYSCALL)) { |
- ExitGroup(1); |
- } |
+ BPF_ASSERT( |
+ std::numeric_limits<int>::max() - kExpectedReturnValue - 1 >= |
+ static_cast<int>(MAX_SYSCALL)); |
+ |
+ StartSandboxOrDie(SyntheticPolicy); |
// TODO(jorgelo): remove this limit once crbug.com/141694 is fixed. |
#if defined(__arm__) |
@@ -275,19 +247,10 @@ void SyntheticProcess(void) { |
continue; |
} |
errno = 0; |
- if (syscall(syscall_number) != -1 || |
- errno != SysnoToRandomErrno(syscall_number)) { |
- // Exit with a return value that is different than kExpectedReturnValue |
- // to signal an error. Make it easy to see what syscall_number failed in |
- // the test report. |
- ExitGroup(kExpectedReturnValue + syscall_number + 1); |
- } |
+ BPF_ASSERT(syscall(syscall_number) == -1); |
+ BPF_ASSERT(errno == SysnoToRandomErrno(syscall_number)); |
} |
- ExitGroup(kExpectedReturnValue); |
-} |
- |
-TEST(SandboxBpf, SyntheticPolicy) { |
- TryPolicyInProcess(SyntheticPolicy, SyntheticProcess); |
+ return true; |
} |
} // namespace |