Index: sandbox/linux/bpf_dsl/bpf_dsl_more_unittest.cc |
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc b/sandbox/linux/bpf_dsl/bpf_dsl_more_unittest.cc |
similarity index 78% |
rename from sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc |
rename to sandbox/linux/bpf_dsl/bpf_dsl_more_unittest.cc |
index 356731e770dde584d1e1080bf031f78ba26102ed..b5d04e1da455d624bec5eea13b2f0e1af4e4dcf0 100644 |
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc |
+++ b/sandbox/linux/bpf_dsl/bpf_dsl_more_unittest.cc |
@@ -31,6 +31,7 @@ |
#include "base/synchronization/waitable_event.h" |
#include "base/threading/thread.h" |
#include "build/build_config.h" |
+#include "sandbox/linux/bpf_dsl/bpf_dsl.h" |
#include "sandbox/linux/seccomp-bpf/bpf_tests.h" |
#include "sandbox/linux/seccomp-bpf/syscall.h" |
#include "sandbox/linux/seccomp-bpf/trap.h" |
@@ -51,6 +52,7 @@ |
#endif |
namespace sandbox { |
+namespace bpf_dsl { |
namespace { |
@@ -103,21 +105,22 @@ intptr_t IncreaseCounter(const struct arch_seccomp_data& args, void* aux) { |
return (*counter)++; |
} |
-class VerboseAPITestingPolicy : public SandboxBPFPolicy { |
+class VerboseAPITestingPolicy : public SandboxBPFDSLPolicy { |
public: |
VerboseAPITestingPolicy(int* counter_ptr) : counter_ptr_(counter_ptr) {} |
+ virtual ~VerboseAPITestingPolicy() {} |
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
- int sysno) const OVERRIDE { |
+ virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE { |
DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
if (sysno == __NR_uname) { |
- return sandbox->Trap(IncreaseCounter, counter_ptr_); |
+ return Trap(IncreaseCounter, counter_ptr_); |
} |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ return Allow(); |
} |
private: |
int* counter_ptr_; |
+ |
DISALLOW_COPY_AND_ASSIGN(VerboseAPITestingPolicy); |
}; |
@@ -140,16 +143,18 @@ SANDBOX_TEST(SandboxBPF, DISABLE_ON_TSAN(VerboseAPITesting)) { |
// A simple blacklist test |
-class BlacklistNanosleepPolicy : public SandboxBPFPolicy { |
+class BlacklistNanosleepPolicy : public SandboxBPFDSLPolicy { |
public: |
BlacklistNanosleepPolicy() {} |
- virtual ErrorCode EvaluateSyscall(SandboxBPF*, int sysno) const OVERRIDE { |
+ virtual ~BlacklistNanosleepPolicy() {} |
+ |
+ virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE { |
DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
switch (sysno) { |
case __NR_nanosleep: |
- return ErrorCode(EACCES); |
+ return Error(EACCES); |
default: |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ return Allow(); |
} |
} |
@@ -170,17 +175,19 @@ BPF_TEST_C(SandboxBPF, ApplyBasicBlacklistPolicy, BlacklistNanosleepPolicy) { |
// Now do a simple whitelist test |
-class WhitelistGetpidPolicy : public SandboxBPFPolicy { |
+class WhitelistGetpidPolicy : public SandboxBPFDSLPolicy { |
public: |
WhitelistGetpidPolicy() {} |
- virtual ErrorCode EvaluateSyscall(SandboxBPF*, int sysno) const OVERRIDE { |
+ virtual ~WhitelistGetpidPolicy() {} |
+ |
+ virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE { |
DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
switch (sysno) { |
case __NR_getpid: |
case __NR_exit_group: |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ return Allow(); |
default: |
- return ErrorCode(ENOMEM); |
+ return Error(ENOMEM); |
} |
} |
@@ -240,41 +247,43 @@ BPF_TEST(SandboxBPF, |
// A simple test that verifies we can return arbitrary errno values. |
-class ErrnoTestPolicy : public SandboxBPFPolicy { |
+class ErrnoTestPolicy : public SandboxBPFDSLPolicy { |
public: |
ErrnoTestPolicy() {} |
- virtual ErrorCode EvaluateSyscall(SandboxBPF*, int sysno) const OVERRIDE; |
+ virtual ~ErrnoTestPolicy() {} |
+ |
+ virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE; |
private: |
DISALLOW_COPY_AND_ASSIGN(ErrnoTestPolicy); |
}; |
-ErrorCode ErrnoTestPolicy::EvaluateSyscall(SandboxBPF*, int sysno) const { |
+ResultExpr ErrnoTestPolicy::EvaluateSyscall(int sysno) const { |
DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
switch (sysno) { |
- case __NR_dup3: // dup2 is a wrapper of dup3 in android |
+ case __NR_dup3: // dup2 is a wrapper of dup3 in android |
#if defined(__NR_dup2) |
case __NR_dup2: |
#endif |
// Pretend that dup2() worked, but don't actually do anything. |
- return ErrorCode(0); |
+ return Error(0); |
case __NR_setuid: |
#if defined(__NR_setuid32) |
case __NR_setuid32: |
#endif |
// Return errno = 1. |
- return ErrorCode(1); |
+ return Error(1); |
case __NR_setgid: |
#if defined(__NR_setgid32) |
case __NR_setgid32: |
#endif |
// Return maximum errno value (typically 4095). |
- return ErrorCode(ErrorCode::ERR_MAX_ERRNO); |
+ return Error(ErrorCode::ERR_MAX_ERRNO); |
case __NR_uname: |
// Return errno = 42; |
- return ErrorCode(42); |
+ return Error(42); |
default: |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ return Allow(); |
} |
} |
@@ -320,22 +329,20 @@ BPF_TEST_C(SandboxBPF, ErrnoTest, ErrnoTestPolicy) { |
// Testing the stacking of two sandboxes |
-class StackingPolicyPartOne : public SandboxBPFPolicy { |
+class StackingPolicyPartOne : public SandboxBPFDSLPolicy { |
public: |
StackingPolicyPartOne() {} |
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
- int sysno) const OVERRIDE { |
+ virtual ~StackingPolicyPartOne() {} |
+ |
+ virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE { |
DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
switch (sysno) { |
- case __NR_getppid: |
- return sandbox->Cond(0, |
- ErrorCode::TP_32BIT, |
- ErrorCode::OP_EQUAL, |
- 0, |
- ErrorCode(ErrorCode::ERR_ALLOWED), |
- ErrorCode(EPERM)); |
+ case __NR_getppid: { |
+ const Arg<int> arg(0); |
+ return If(arg == 0, Allow()).Else(Error(EPERM)); |
+ } |
default: |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ return Allow(); |
} |
} |
@@ -343,22 +350,20 @@ class StackingPolicyPartOne : public SandboxBPFPolicy { |
DISALLOW_COPY_AND_ASSIGN(StackingPolicyPartOne); |
}; |
-class StackingPolicyPartTwo : public SandboxBPFPolicy { |
+class StackingPolicyPartTwo : public SandboxBPFDSLPolicy { |
public: |
StackingPolicyPartTwo() {} |
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
- int sysno) const OVERRIDE { |
+ virtual ~StackingPolicyPartTwo() {} |
+ |
+ virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE { |
DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
switch (sysno) { |
- case __NR_getppid: |
- return sandbox->Cond(0, |
- ErrorCode::TP_32BIT, |
- ErrorCode::OP_EQUAL, |
- 0, |
- ErrorCode(EINVAL), |
- ErrorCode(ErrorCode::ERR_ALLOWED)); |
+ case __NR_getppid: { |
+ const Arg<int> arg(0); |
+ return If(arg == 0, Error(EINVAL)).Else(Allow()); |
+ } |
default: |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ return Allow(); |
} |
} |
@@ -403,17 +408,19 @@ int SysnoToRandomErrno(int sysno) { |
return ((sysno & ~3) >> 2) % 29 + 1; |
} |
-class SyntheticPolicy : public SandboxBPFPolicy { |
+class SyntheticPolicy : public SandboxBPFDSLPolicy { |
public: |
SyntheticPolicy() {} |
- virtual ErrorCode EvaluateSyscall(SandboxBPF*, int sysno) const OVERRIDE { |
+ virtual ~SyntheticPolicy() {} |
+ |
+ virtual ResultExpr EvaluateSyscall(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 Allow(); |
} |
- return ErrorCode(SysnoToRandomErrno(sysno)); |
+ return Error(SysnoToRandomErrno(sysno)); |
} |
private: |
@@ -454,18 +461,20 @@ int ArmPrivateSysnoToErrno(int sysno) { |
} |
} |
-class ArmPrivatePolicy : public SandboxBPFPolicy { |
+class ArmPrivatePolicy : public SandboxBPFDSLPolicy { |
public: |
ArmPrivatePolicy() {} |
- virtual ErrorCode EvaluateSyscall(SandboxBPF*, int sysno) const OVERRIDE { |
+ virtual ~ArmPrivatePolicy() {} |
+ |
+ virtual ResultExpr EvaluateSyscall(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 Error(ArmPrivateSysnoToErrno(sysno)); |
} |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ return Allow(); |
} |
private: |
@@ -557,22 +566,23 @@ intptr_t PrctlHandler(const struct arch_seccomp_data& args, void*) { |
} |
} |
-class PrctlPolicy : public SandboxBPFPolicy { |
+class PrctlPolicy : public SandboxBPFDSLPolicy { |
public: |
PrctlPolicy() {} |
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
- int sysno) const OVERRIDE { |
+ virtual ~PrctlPolicy() {} |
+ |
+ virtual ResultExpr EvaluateSyscall(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); |
+ return UnsafeTrap(PrctlHandler, NULL); |
} |
// Allow all other system calls. |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ return Allow(); |
} |
private: |
@@ -610,18 +620,18 @@ intptr_t AllowRedirectedSyscall(const struct arch_seccomp_data& args, void*) { |
return SandboxBPF::ForwardSyscall(args); |
} |
-class RedirectAllSyscallsPolicy : public SandboxBPFPolicy { |
+class RedirectAllSyscallsPolicy : public SandboxBPFDSLPolicy { |
public: |
RedirectAllSyscallsPolicy() {} |
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
- int sysno) const OVERRIDE; |
+ virtual ~RedirectAllSyscallsPolicy() {} |
+ |
+ virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE; |
private: |
DISALLOW_COPY_AND_ASSIGN(RedirectAllSyscallsPolicy); |
}; |
-ErrorCode RedirectAllSyscallsPolicy::EvaluateSyscall(SandboxBPF* sandbox, |
- int sysno) const { |
+ResultExpr RedirectAllSyscallsPolicy::EvaluateSyscall(int sysno) const { |
DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
setenv(kSandboxDebuggingEnv, "t", 0); |
Die::SuppressInfoMessages(true); |
@@ -629,8 +639,8 @@ ErrorCode RedirectAllSyscallsPolicy::EvaluateSyscall(SandboxBPF* sandbox, |
// Some system calls must always be allowed, if our policy wants to make |
// use of UnsafeTrap() |
if (SandboxBPF::IsRequiredForUnsafeTrap(sysno)) |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
- return sandbox->UnsafeTrap(AllowRedirectedSyscall, NULL); |
+ return Allow(); |
+ return UnsafeTrap(AllowRedirectedSyscall, NULL); |
} |
int bus_handler_fd_ = -1; |
@@ -714,7 +724,9 @@ BPF_TEST_C(SandboxBPF, UnsafeTrapWithErrno, RedirectAllSyscallsPolicy) { |
BPF_ASSERT(errno == 0); |
} |
-bool NoOpCallback() { return true; } |
+bool NoOpCallback() { |
+ return true; |
+} |
// Test a trap handler that makes use of a broker process to open(). |
@@ -746,7 +758,7 @@ intptr_t BrokerOpenTrapHandler(const struct arch_seccomp_data& args, |
BPF_ASSERT(aux); |
BrokerProcess* broker_process = static_cast<BrokerProcess*>(aux); |
switch (args.nr) { |
- case __NR_faccessat: // access is a wrapper of faccessat in android |
+ case __NR_faccessat: // access is a wrapper of faccessat in android |
BPF_ASSERT(static_cast<int>(args.args[0]) == AT_FDCWD); |
return broker_process->Access(reinterpret_cast<const char*>(args.args[1]), |
static_cast<int>(args.args[2])); |
@@ -846,18 +858,18 @@ BPF_TEST(SandboxBPF, |
// Simple test demonstrating how to use SandboxBPF::Cond() |
-class SimpleCondTestPolicy : public SandboxBPFPolicy { |
+class SimpleCondTestPolicy : public SandboxBPFDSLPolicy { |
public: |
SimpleCondTestPolicy() {} |
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
- int sysno) const OVERRIDE; |
+ virtual ~SimpleCondTestPolicy() {} |
+ |
+ virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE; |
private: |
DISALLOW_COPY_AND_ASSIGN(SimpleCondTestPolicy); |
}; |
-ErrorCode SimpleCondTestPolicy::EvaluateSyscall(SandboxBPF* sandbox, |
- int sysno) const { |
+ResultExpr SimpleCondTestPolicy::EvaluateSyscall(int sysno) const { |
DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
// We deliberately return unusual errno values upon failure, so that we |
@@ -869,34 +881,24 @@ ErrorCode SimpleCondTestPolicy::EvaluateSyscall(SandboxBPF* sandbox, |
case __NR_open: |
flags_argument_position = 1; |
#endif |
- case __NR_openat: // open can be a wrapper for openat(2). |
+ case __NR_openat: { // open can be a wrapper for openat(2). |
if (sysno == __NR_openat) |
flags_argument_position = 2; |
// Allow opening files for reading, but don't allow writing. |
COMPILE_ASSERT(O_RDONLY == 0, O_RDONLY_must_be_all_zero_bits); |
- return sandbox->Cond(flags_argument_position, |
- ErrorCode::TP_32BIT, |
- ErrorCode::OP_HAS_ANY_BITS, |
- O_ACCMODE /* 0x3 */, |
- ErrorCode(EROFS), |
- ErrorCode(ErrorCode::ERR_ALLOWED)); |
- case __NR_prctl: |
+ const Arg<int> flags(flags_argument_position); |
+ return If((flags & O_ACCMODE) != 0, Error(EROFS)).Else(Allow()); |
+ } |
+ case __NR_prctl: { |
// Allow prctl(PR_SET_DUMPABLE) and prctl(PR_GET_DUMPABLE), but |
// disallow everything else. |
- return sandbox->Cond(0, |
- ErrorCode::TP_32BIT, |
- ErrorCode::OP_EQUAL, |
- PR_SET_DUMPABLE, |
- ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Cond(0, |
- ErrorCode::TP_32BIT, |
- ErrorCode::OP_EQUAL, |
- PR_GET_DUMPABLE, |
- ErrorCode(ErrorCode::ERR_ALLOWED), |
- ErrorCode(ENOMEM))); |
+ const Arg<int> option(0); |
+ return If(option == PR_SET_DUMPABLE || option == PR_GET_DUMPABLE, Allow()) |
+ .Else(Error(ENOMEM)); |
+ } |
default: |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ return Allow(); |
} |
} |
@@ -1233,47 +1235,31 @@ BPF_TEST(SandboxBPF, |
BPF_AUX->VerifyFilter(); |
} |
-class EqualityArgumentWidthPolicy : public SandboxBPFPolicy { |
+class EqualityArgumentWidthPolicy : public SandboxBPFDSLPolicy { |
public: |
EqualityArgumentWidthPolicy() {} |
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
- int sysno) const OVERRIDE; |
+ virtual ~EqualityArgumentWidthPolicy() {} |
+ |
+ virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE; |
private: |
DISALLOW_COPY_AND_ASSIGN(EqualityArgumentWidthPolicy); |
}; |
-ErrorCode EqualityArgumentWidthPolicy::EvaluateSyscall(SandboxBPF* sandbox, |
- int sysno) const { |
+ResultExpr EqualityArgumentWidthPolicy::EvaluateSyscall(int sysno) const { |
DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
if (sysno == __NR_uname) { |
- return sandbox->Cond( |
- 0, |
- ErrorCode::TP_32BIT, |
- ErrorCode::OP_EQUAL, |
- 0, |
- sandbox->Cond(1, |
- ErrorCode::TP_32BIT, |
- ErrorCode::OP_EQUAL, |
- 0x55555555, |
- ErrorCode(1), |
- ErrorCode(2)), |
- // The BPF compiler and the BPF interpreter in the kernel are |
- // (mostly) agnostic of the host platform's word size. The compiler |
- // will happily generate code that tests a 64bit value, and the |
- // interpreter will happily perform this test. |
- // But unless there is a kernel bug, there is no way for us to pass |
- // in a 64bit quantity on a 32bit platform. The upper 32bits should |
- // always be zero. So, this test should always evaluate as false on |
- // 32bit systems. |
- sandbox->Cond(1, |
- ErrorCode::TP_64BIT, |
- ErrorCode::OP_EQUAL, |
- 0x55555555AAAAAAAAULL, |
- ErrorCode(1), |
- ErrorCode(2))); |
+ const Arg<int> option(0); |
+ const Arg<uint32_t> arg32(1); |
+ const Arg<uint64_t> arg64(1); |
+ return Switch(option) |
+ .Case(0, If(arg32 == 0x55555555, Error(1)).Else(Error(2))) |
+#if __SIZEOF_POINTER__ > 4 |
+ .Case(1, If(arg64 == 0x55555555AAAAAAAAULL, Error(1)).Else(Error(2))) |
+#endif |
+ .Default(Error(3)); |
} |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ return Allow(); |
} |
BPF_TEST_C(SandboxBPF, EqualityArgumentWidth, EqualityArgumentWidthPolicy) { |
@@ -1287,8 +1273,6 @@ BPF_TEST_C(SandboxBPF, EqualityArgumentWidth, EqualityArgumentWidthPolicy) { |
BPF_ASSERT(Syscall::Call(__NR_uname, 1, 0x5555555500000000ULL) == -2); |
BPF_ASSERT(Syscall::Call(__NR_uname, 1, 0x5555555511111111ULL) == -2); |
BPF_ASSERT(Syscall::Call(__NR_uname, 1, 0x11111111AAAAAAAAULL) == -2); |
-#else |
- BPF_ASSERT(Syscall::Call(__NR_uname, 1, 0x55555555) == -2); |
jln (very slow on Chromium)
2014/09/12 23:52:57
Why removed?
mdempsky
2014/09/13 00:20:24
This assert was testing TP_64BIT on a 32-bit syste
|
#endif |
} |
@@ -1304,21 +1288,21 @@ BPF_DEATH_TEST_C(SandboxBPF, |
} |
#endif |
-class EqualityWithNegativeArgumentsPolicy : public SandboxBPFPolicy { |
+class EqualityWithNegativeArgumentsPolicy : public SandboxBPFDSLPolicy { |
public: |
EqualityWithNegativeArgumentsPolicy() {} |
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
- int sysno) const OVERRIDE { |
+ virtual ~EqualityWithNegativeArgumentsPolicy() {} |
+ |
+ virtual ResultExpr EvaluateSyscall(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)); |
+ // TODO(mdempsky): This currently can't be Arg<int> because then |
+ // 0xFFFFFFFF will be treated as a (signed) int, and then when |
+ // Arg::EqualTo casts it to uint64_t, it will be sign extended. |
+ const Arg<unsigned> arg(0); |
+ return If(arg == 0xFFFFFFFF, Error(1)).Else(Error(2)); |
} |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ return Allow(); |
} |
private: |
@@ -1344,83 +1328,64 @@ BPF_DEATH_TEST_C(SandboxBPF, |
BPF_ASSERT(Syscall::Call(__NR_uname, 0xFFFFFFFF00000000LL) == -1); |
} |
#endif |
-class AllBitTestPolicy : public SandboxBPFPolicy { |
+ |
+class AllBitTestPolicy : public SandboxBPFDSLPolicy { |
public: |
AllBitTestPolicy() {} |
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
- int sysno) const OVERRIDE; |
+ virtual ~AllBitTestPolicy() {} |
+ |
+ virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE; |
private: |
+ static ResultExpr HasAllBits32(uint32_t bits); |
+ static ResultExpr HasAllBits64(uint64_t bits); |
+ |
DISALLOW_COPY_AND_ASSIGN(AllBitTestPolicy); |
}; |
-ErrorCode AllBitTestPolicy::EvaluateSyscall(SandboxBPF* sandbox, |
- int sysno) const { |
+ResultExpr AllBitTestPolicy::HasAllBits32(uint32_t bits) { |
+ if (bits == 0) { |
+ return Error(1); |
+ } |
+ const Arg<uint32_t> arg(1); |
+ return If((arg & bits) == bits, Error(1)).Else(Error(0)); |
+} |
+ |
+ResultExpr AllBitTestPolicy::HasAllBits64(uint64_t bits) { |
+ if (bits == 0) { |
+ return Error(1); |
+ } |
+ const Arg<uint64_t> arg(1); |
+ return If((arg & bits) == bits, Error(1)).Else(Error(0)); |
+} |
+ |
+ResultExpr AllBitTestPolicy::EvaluateSyscall(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 |
+ // Test masked-equality cases that should trigger the "has all bits" |
+ // peephole optimizations. 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 (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, |
- ErrorCode(1), ErrorCode(0)), |
- |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 1, |
- sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ALL_BITS, |
- 0x1, |
- ErrorCode(1), ErrorCode(0)), |
- |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 2, |
- sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ALL_BITS, |
- 0x3, |
- ErrorCode(1), ErrorCode(0)), |
- |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 3, |
- sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ALL_BITS, |
- 0x80000000, |
- ErrorCode(1), ErrorCode(0)), |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 4, |
- sandbox->Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ALL_BITS, |
- 0x0, |
- ErrorCode(1), ErrorCode(0)), |
- |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 5, |
- sandbox->Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ALL_BITS, |
- 0x1, |
- ErrorCode(1), ErrorCode(0)), |
- |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 6, |
- sandbox->Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ALL_BITS, |
- 0x3, |
- ErrorCode(1), ErrorCode(0)), |
- |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 7, |
- sandbox->Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ALL_BITS, |
- 0x80000000, |
- ErrorCode(1), ErrorCode(0)), |
- |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 8, |
- sandbox->Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ALL_BITS, |
- 0x100000000ULL, |
- ErrorCode(1), ErrorCode(0)), |
- |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 9, |
- sandbox->Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ALL_BITS, |
- 0x300000000ULL, |
- ErrorCode(1), ErrorCode(0)), |
- |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 10, |
- sandbox->Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ALL_BITS, |
- 0x100000001ULL, |
- ErrorCode(1), ErrorCode(0)), |
- |
- sandbox->Kill("Invalid test case number")))))))))))); |
+ const Arg<int> option(0); |
+ return Switch(option) |
+ .Case(0, HasAllBits32(0x0)) |
+ .Case(1, HasAllBits32(0x1)) |
+ .Case(2, HasAllBits32(0x3)) |
+ .Case(3, HasAllBits32(0x80000000)) |
+#if __SIZEOF_POINTER__ > 4 |
+ .Case(4, HasAllBits64(0x0)) |
+ .Case(5, HasAllBits64(0x1)) |
+ .Case(6, HasAllBits64(0x3)) |
+ .Case(7, HasAllBits64(0x80000000)) |
+ .Case(8, HasAllBits64(0x100000000ULL)) |
+ .Case(9, HasAllBits64(0x300000000ULL)) |
+ .Case(10, HasAllBits64(0x100000001ULL)) |
+#endif |
+ .Default(Kill("Invalid test case number")); |
} |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ return Allow(); |
} |
// Define a macro that performs tests using our test policy. |
@@ -1473,6 +1438,7 @@ BPF_TEST_C(SandboxBPF, AllBitTests, AllBitTestPolicy) { |
BITMASK_TEST( 3, 0xC0000000U, ALLBITS32, 0x80000000, EXPECT_SUCCESS); |
BITMASK_TEST( 3, -0x80000000LL, ALLBITS32, 0x80000000, EXPECT_SUCCESS); |
+#if __SIZEOF_POINTER__ > 4 |
// 64bit test: all of 0x0 (should always be true) |
BITMASK_TEST( 4, 0, ALLBITS64, 0, EXPECT_SUCCESS); |
BITMASK_TEST( 4, 1, ALLBITS64, 0, EXPECT_SUCCESS); |
@@ -1546,88 +1512,66 @@ BPF_TEST_C(SandboxBPF, AllBitTests, AllBitTestPolicy) { |
BITMASK_TEST(10, 0x100000001LL, ALLBITS64,0x100000001, EXPT64_SUCCESS); |
BITMASK_TEST(10, 0xFFFFFFFFU, ALLBITS64,0x100000001, EXPECT_FAILURE); |
BITMASK_TEST(10, -1L, ALLBITS64,0x100000001, EXPT64_SUCCESS); |
+#endif |
} |
-class AnyBitTestPolicy : public SandboxBPFPolicy { |
+class AnyBitTestPolicy : public SandboxBPFDSLPolicy { |
public: |
AnyBitTestPolicy() {} |
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
- int sysno) const OVERRIDE; |
+ virtual ~AnyBitTestPolicy() {} |
+ |
+ virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE; |
private: |
+ static ResultExpr HasAnyBits32(uint32_t); |
+ static ResultExpr HasAnyBits64(uint64_t); |
+ |
DISALLOW_COPY_AND_ASSIGN(AnyBitTestPolicy); |
}; |
-ErrorCode AnyBitTestPolicy::EvaluateSyscall(SandboxBPF* sandbox, |
- int sysno) const { |
+ResultExpr AnyBitTestPolicy::HasAnyBits32(uint32_t bits) { |
+ if (bits == 0) { |
+ return Error(0); |
+ } |
+ const Arg<uint32_t> arg(1); |
+ return If((arg & bits) != 0, Error(1)).Else(Error(0)); |
+} |
+ |
+ResultExpr AnyBitTestPolicy::HasAnyBits64(uint64_t bits) { |
+ if (bits == 0) { |
+ return Error(0); |
+ } |
+ const Arg<uint64_t> arg(1); |
+ return If((arg & bits) != 0, Error(1)).Else(Error(0)); |
+} |
+ |
+ResultExpr AnyBitTestPolicy::EvaluateSyscall(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 |
+ // Test masked-equality cases that should trigger the "has any bits" |
+ // peephole optimizations. 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 (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, |
- ErrorCode(1), ErrorCode(0)), |
- |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 1, |
- sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, |
- 0x1, |
- ErrorCode(1), ErrorCode(0)), |
- |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 2, |
- sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, |
- 0x3, |
- ErrorCode(1), ErrorCode(0)), |
- |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 3, |
- sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, |
- 0x80000000, |
- ErrorCode(1), ErrorCode(0)), |
- |
- // All the following tests don't really make much sense on 32bit |
- // systems. They will always evaluate as false. |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 4, |
- sandbox->Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ANY_BITS, |
- 0x0, |
- ErrorCode(1), ErrorCode(0)), |
- |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 5, |
- sandbox->Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ANY_BITS, |
- 0x1, |
- ErrorCode(1), ErrorCode(0)), |
- |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 6, |
- sandbox->Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ANY_BITS, |
- 0x3, |
- ErrorCode(1), ErrorCode(0)), |
- |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 7, |
- sandbox->Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ANY_BITS, |
- 0x80000000, |
- ErrorCode(1), ErrorCode(0)), |
- |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 8, |
- sandbox->Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ANY_BITS, |
- 0x100000000ULL, |
- ErrorCode(1), ErrorCode(0)), |
- |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 9, |
- sandbox->Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ANY_BITS, |
- 0x300000000ULL, |
- ErrorCode(1), ErrorCode(0)), |
- |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 10, |
- sandbox->Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ANY_BITS, |
- 0x100000001ULL, |
- ErrorCode(1), ErrorCode(0)), |
- |
- sandbox->Kill("Invalid test case number")))))))))))); |
+ const Arg<int> option(0); |
+ return Switch(option) |
+ .Case(0, HasAnyBits32(0x0)) |
+ .Case(1, HasAnyBits32(0x1)) |
+ .Case(2, HasAnyBits32(0x3)) |
+ .Case(3, HasAnyBits32(0x80000000)) |
+#if __SIZEOF_POINTER__ > 4 |
+ .Case(4, HasAnyBits64(0x0)) |
+ .Case(5, HasAnyBits64(0x1)) |
+ .Case(6, HasAnyBits64(0x3)) |
+ .Case(7, HasAnyBits64(0x80000000)) |
+ .Case(8, HasAnyBits64(0x100000000ULL)) |
+ .Case(9, HasAnyBits64(0x300000000ULL)) |
+ .Case(10, HasAnyBits64(0x100000001ULL)) |
+#endif |
+ .Default(Kill("Invalid test case number")); |
} |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ return Allow(); |
} |
BPF_TEST_C(SandboxBPF, AnyBitTests, AnyBitTestPolicy) { |
@@ -1658,6 +1602,7 @@ BPF_TEST_C(SandboxBPF, AnyBitTests, AnyBitTestPolicy) { |
BITMASK_TEST( 3, 0xC0000000U, ANYBITS32, 0x80000000, EXPECT_SUCCESS); |
BITMASK_TEST( 3, -0x80000000LL, ANYBITS32, 0x80000000, EXPECT_SUCCESS); |
+#if __SIZEOF_POINTER__ > 4 |
// 64bit test: any of 0x0 (should always be false) |
BITMASK_TEST( 4, 0, ANYBITS64, 0x0, EXPECT_FAILURE); |
BITMASK_TEST( 4, 1, ANYBITS64, 0x0, EXPECT_FAILURE); |
@@ -1731,57 +1676,48 @@ BPF_TEST_C(SandboxBPF, AnyBitTests, AnyBitTestPolicy) { |
BITMASK_TEST( 10, 0x100000001LL, ANYBITS64,0x100000001, EXPECT_SUCCESS); |
BITMASK_TEST( 10, 0xFFFFFFFFU, ANYBITS64,0x100000001, EXPECT_SUCCESS); |
BITMASK_TEST( 10, -1L, ANYBITS64,0x100000001, EXPECT_SUCCESS); |
+#endif |
} |
-class MaskedEqualTestPolicy : public SandboxBPFPolicy { |
+class MaskedEqualTestPolicy : public SandboxBPFDSLPolicy { |
public: |
MaskedEqualTestPolicy() {} |
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
- int sysno) const OVERRIDE; |
+ virtual ~MaskedEqualTestPolicy() {} |
- private: |
- struct Rule { |
- ErrorCode::ArgType arg_type; |
- uint64_t mask; |
- uint64_t value; |
- }; |
+ virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE; |
- static Rule rules[]; |
+ private: |
+ static ResultExpr MaskedEqual32(uint32_t mask, uint32_t value); |
+ static ResultExpr MaskedEqual64(uint64_t mask, uint64_t value); |
DISALLOW_COPY_AND_ASSIGN(MaskedEqualTestPolicy); |
}; |
-MaskedEqualTestPolicy::Rule MaskedEqualTestPolicy::rules[] = { |
- /* 0 = */ {ErrorCode::TP_32BIT, 0x0000000000ff00ff, 0x00000000005500aa}, |
+ResultExpr MaskedEqualTestPolicy::MaskedEqual32(uint32_t mask, uint32_t value) { |
+ const Arg<uint32_t> arg(1); |
+ return If((arg & mask) == value, Error(1)).Else(Error(0)); |
+} |
-#if __SIZEOF_POINTER__ > 4 |
- /* 1 = */ {ErrorCode::TP_64BIT, 0x00ff00ff00000000, 0x005500aa00000000}, |
- /* 2 = */ {ErrorCode::TP_64BIT, 0x00ff00ff00ff00ff, 0x005500aa005500aa}, |
-#endif |
-}; |
+ResultExpr MaskedEqualTestPolicy::MaskedEqual64(uint64_t mask, uint64_t value) { |
+ const Arg<uint64_t> arg(1); |
+ return If((arg & mask) == value, Error(1)).Else(Error(0)); |
+} |
-ErrorCode MaskedEqualTestPolicy::EvaluateSyscall(SandboxBPF* sandbox, |
- int sysno) const { |
+ResultExpr MaskedEqualTestPolicy::EvaluateSyscall(int sysno) const { |
DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
if (sysno == __NR_uname) { |
- ErrorCode err = sandbox->Kill("Invalid test case number"); |
- for (size_t i = 0; i < arraysize(rules); i++) { |
- err = sandbox->Cond(0, |
- ErrorCode::TP_32BIT, |
- ErrorCode::OP_EQUAL, |
- i, |
- sandbox->CondMaskedEqual(1, |
- rules[i].arg_type, |
- rules[i].mask, |
- rules[i].value, |
- ErrorCode(1), |
- ErrorCode(0)), |
- err); |
- } |
- return err; |
+ const Arg<int> option(0); |
+ return Switch(option) |
+ .Case(0, MaskedEqual32(0x00ff00ff, 0x005500aa)) |
+#if __SIZEOF_POINTER__ > 4 |
+ .Case(1, MaskedEqual64(0x00ff00ff00000000, 0x005500aa00000000)) |
+ .Case(2, MaskedEqual64(0x00ff00ff00ff00ff, 0x005500aa005500aa)) |
+#endif |
+ .Default(Kill("Invalid test case number")); |
} |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ |
+ return Allow(); |
} |
#define MASKEQ_TEST(rulenum, arg, expected_result) \ |
@@ -1870,18 +1806,18 @@ intptr_t PthreadTrapHandler(const struct arch_seccomp_data& args, void* aux) { |
return -EPERM; |
} |
-class PthreadPolicyEquality : public SandboxBPFPolicy { |
+class PthreadPolicyEquality : public SandboxBPFDSLPolicy { |
public: |
PthreadPolicyEquality() {} |
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
- int sysno) const OVERRIDE; |
+ virtual ~PthreadPolicyEquality() {} |
+ |
+ virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE; |
private: |
DISALLOW_COPY_AND_ASSIGN(PthreadPolicyEquality); |
}; |
-ErrorCode PthreadPolicyEquality::EvaluateSyscall(SandboxBPF* sandbox, |
- int sysno) const { |
+ResultExpr PthreadPolicyEquality::EvaluateSyscall(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 |
@@ -1897,39 +1833,48 @@ ErrorCode PthreadPolicyEquality::EvaluateSyscall(SandboxBPF* sandbox, |
// The following policy is very strict. It only allows the exact masks |
// that we have seen in known implementations. It is probably somewhat |
// stricter than what we would want to do. |
- const uint64_t kGlibcCloneMask = |
- CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | |
- CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS | |
- CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID; |
- const uint64_t kBaseAndroidCloneMask = |
- CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | |
- CLONE_THREAD | CLONE_SYSVSEM; |
- return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
- kGlibcCloneMask, |
- ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
- kBaseAndroidCloneMask | CLONE_DETACHED, |
- ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
- kBaseAndroidCloneMask, |
- ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Trap(PthreadTrapHandler, "Unknown mask")))); |
+ const uint64_t kGlibcCloneMask = CLONE_VM | CLONE_FS | CLONE_FILES | |
+ CLONE_SIGHAND | CLONE_THREAD | |
+ CLONE_SYSVSEM | CLONE_SETTLS | |
+ CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID; |
+ const uint64_t kBaseAndroidCloneMask = CLONE_VM | CLONE_FS | CLONE_FILES | |
+ CLONE_SIGHAND | CLONE_THREAD | |
+ CLONE_SYSVSEM; |
+ const Arg<unsigned long> flags(0); |
+ return If(flags == kGlibcCloneMask || |
+ flags == (kBaseAndroidCloneMask | CLONE_DETACHED) || |
+ flags == kBaseAndroidCloneMask, |
+ Allow()).Else(Trap(PthreadTrapHandler, "Unknown mask")); |
} |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ |
+ return Allow(); |
} |
-class PthreadPolicyBitMask : public SandboxBPFPolicy { |
+class PthreadPolicyBitMask : public SandboxBPFDSLPolicy { |
public: |
PthreadPolicyBitMask() {} |
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
- int sysno) const OVERRIDE; |
+ virtual ~PthreadPolicyBitMask() {} |
+ |
+ virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE; |
private: |
+ static BoolExpr HasAnyBits(const Arg<unsigned long>& arg, unsigned long bits); |
+ static BoolExpr HasAllBits(const Arg<unsigned long>& arg, unsigned long bits); |
+ |
DISALLOW_COPY_AND_ASSIGN(PthreadPolicyBitMask); |
}; |
-ErrorCode PthreadPolicyBitMask::EvaluateSyscall(SandboxBPF* sandbox, |
- int sysno) const { |
+BoolExpr PthreadPolicyBitMask::HasAnyBits(const Arg<unsigned long>& arg, |
+ unsigned long bits) { |
+ return (arg & bits) != 0; |
+} |
+ |
+BoolExpr PthreadPolicyBitMask::HasAllBits(const Arg<unsigned long>& arg, |
+ unsigned long bits) { |
+ return (arg & bits) == bits; |
+} |
+ |
+ResultExpr PthreadPolicyBitMask::EvaluateSyscall(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 |
@@ -1945,30 +1890,31 @@ ErrorCode PthreadPolicyBitMask::EvaluateSyscall(SandboxBPF* sandbox, |
// err on the side of rather safe than sorry. |
// Very noticeably though, we disallow fork() (which is often just a |
// wrapper around clone()). |
- return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, |
- ~uint32(CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND| |
- CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS| |
- CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID| |
- CLONE_DETACHED), |
- sandbox->Trap(PthreadTrapHandler, |
- "Unexpected CLONE_XXX flag found"), |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ALL_BITS, |
- CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND| |
- CLONE_THREAD|CLONE_SYSVSEM, |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ALL_BITS, |
- CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, |
- ErrorCode(ErrorCode::ERR_ALLOWED), |
- sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, |
- CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, |
- sandbox->Trap(PthreadTrapHandler, |
- "Must set either all or none of the TLS" |
- " and futex bits in call to clone()"), |
- ErrorCode(ErrorCode::ERR_ALLOWED))), |
- sandbox->Trap(PthreadTrapHandler, |
- "Missing mandatory CLONE_XXX flags " |
- "when creating new thread"))); |
+ const unsigned long kMandatoryFlags = CLONE_VM | CLONE_FS | CLONE_FILES | |
+ CLONE_SIGHAND | CLONE_THREAD | |
+ CLONE_SYSVSEM; |
+ const unsigned long kFutexFlags = |
+ CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID; |
+ const unsigned long kNoopFlags = CLONE_DETACHED; |
+ const unsigned long kKnownFlags = |
+ kMandatoryFlags | kFutexFlags | kNoopFlags; |
+ |
+ const Arg<unsigned long> flags(0); |
+ return If(HasAnyBits(flags, ~kKnownFlags), |
+ Trap(PthreadTrapHandler, "Unexpected CLONE_XXX flag found")) |
+ .ElseIf(!HasAllBits(flags, kMandatoryFlags), |
+ Trap(PthreadTrapHandler, |
+ "Missing mandatory CLONE_XXX flags " |
+ "when creating new thread")) |
+ .ElseIf( |
+ !HasAllBits(flags, kFutexFlags) && HasAnyBits(flags, kFutexFlags), |
+ Trap(PthreadTrapHandler, |
+ "Must set either all or none of the TLS and futex bits in " |
+ "call to clone()")) |
+ .Else(Allow()); |
} |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ |
+ return Allow(); |
} |
static void* ThreadFnc(void* arg) { |
@@ -2075,14 +2021,13 @@ long SetSyscall(pid_t pid, regs_struct* regs, int syscall_number) { |
const uint16_t kTraceData = 0xcc; |
-class TraceAllPolicy : public SandboxBPFPolicy { |
+class TraceAllPolicy : public SandboxBPFDSLPolicy { |
public: |
TraceAllPolicy() {} |
virtual ~TraceAllPolicy() {} |
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler, |
- int system_call_number) const OVERRIDE { |
- return ErrorCode(ErrorCode::ERR_TRACE + kTraceData); |
+ virtual ResultExpr EvaluateSyscall(int system_call_number) const OVERRIDE { |
+ return Trace(kTraceData); |
} |
private: |
@@ -2137,8 +2082,11 @@ SANDBOX_TEST(SandboxBPF, DISABLE_ON_TSAN(SeccompRetTrace)) { |
BPF_ASSERT(HANDLE_EINTR(waitpid(pid, &status, WUNTRACED)) != -1); |
BPF_ASSERT(WIFSTOPPED(status)); |
- BPF_ASSERT_NE(-1, ptrace(PTRACE_SETOPTIONS, pid, NULL, |
- reinterpret_cast<void*>(PTRACE_O_TRACESECCOMP))); |
+ BPF_ASSERT_NE(-1, |
+ ptrace(PTRACE_SETOPTIONS, |
+ pid, |
+ NULL, |
+ reinterpret_cast<void*>(PTRACE_O_TRACESECCOMP))); |
BPF_ASSERT_NE(-1, ptrace(PTRACE_CONT, pid, NULL, NULL)); |
while (true) { |
BPF_ASSERT(HANDLE_EINTR(waitpid(pid, &status, 0)) != -1); |
@@ -2219,22 +2167,21 @@ bool FullPread64(int fd, char* buffer, size_t count, off64_t offset) { |
bool pread_64_was_forwarded = false; |
-class TrapPread64Policy : public SandboxBPFPolicy { |
+class TrapPread64Policy : public SandboxBPFDSLPolicy { |
public: |
TrapPread64Policy() {} |
virtual ~TrapPread64Policy() {} |
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler, |
- int system_call_number) const OVERRIDE { |
+ virtual ResultExpr EvaluateSyscall(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 UnsafeTrap(ForwardPreadHandler, NULL); |
} |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ return Allow(); |
} |
private: |
@@ -2245,6 +2192,7 @@ class TrapPread64Policy : public SandboxBPFPolicy { |
return SandboxBPF::ForwardSyscall(args); |
} |
+ |
DISALLOW_COPY_AND_ASSIGN(TrapPread64Policy); |
}; |
@@ -2286,7 +2234,7 @@ void* TsyncApplyToTwoThreadsFunc(void* cond_ptr) { |
SANDBOX_TEST(SandboxBPF, Tsync) { |
if (SandboxBPF::SupportsSeccompThreadFilterSynchronization() != |
- SandboxBPF::STATUS_AVAILABLE) { |
+ SandboxBPF::STATUS_AVAILABLE) { |
return; |
} |
@@ -2294,8 +2242,8 @@ SANDBOX_TEST(SandboxBPF, Tsync) { |
// Create a thread on which to invoke the blocked syscall. |
pthread_t thread; |
- BPF_ASSERT_EQ(0, |
- pthread_create(&thread, NULL, &TsyncApplyToTwoThreadsFunc, &event)); |
+ BPF_ASSERT_EQ( |
+ 0, pthread_create(&thread, NULL, &TsyncApplyToTwoThreadsFunc, &event)); |
// Test that nanoseelp success. |
const struct timespec ts = {0, 0}; |
@@ -2316,21 +2264,22 @@ SANDBOX_TEST(SandboxBPF, Tsync) { |
BPF_ASSERT_EQ(0, pthread_join(thread, NULL)); |
} |
-class AllowAllPolicy : public SandboxBPFPolicy { |
+class AllowAllPolicy : public SandboxBPFDSLPolicy { |
public: |
- AllowAllPolicy() : SandboxBPFPolicy() {} |
+ AllowAllPolicy() {} |
virtual ~AllowAllPolicy() {} |
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
- int sysno) const OVERRIDE { |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE { |
+ return Allow(); |
} |
private: |
DISALLOW_COPY_AND_ASSIGN(AllowAllPolicy); |
}; |
-SANDBOX_DEATH_TEST(SandboxBPF, StartMultiThreadedAsSingleThreaded, |
+SANDBOX_DEATH_TEST( |
+ SandboxBPF, |
+ StartMultiThreadedAsSingleThreaded, |
DEATH_MESSAGE("Cannot start sandbox; process is already multi-threaded")) { |
base::Thread thread("sandbox.linux.StartMultiThreadedAsSingleThreaded"); |
BPF_ASSERT(thread.Start()); |
@@ -2342,9 +2291,12 @@ SANDBOX_DEATH_TEST(SandboxBPF, StartMultiThreadedAsSingleThreaded, |
// http://crbug.com/407357 |
#if !defined(THREAD_SANITIZER) |
-SANDBOX_DEATH_TEST(SandboxBPF, StartSingleThreadedAsMultiThreaded, |
- DEATH_MESSAGE("Cannot start sandbox; process may be single-threaded when " |
- "reported as not")) { |
+SANDBOX_DEATH_TEST( |
+ SandboxBPF, |
+ StartSingleThreadedAsMultiThreaded, |
+ DEATH_MESSAGE( |
+ "Cannot start sandbox; process may be single-threaded when " |
+ "reported as not")) { |
SandboxBPF sandbox; |
sandbox.SetSandboxPolicy(new AllowAllPolicy()); |
BPF_ASSERT(!sandbox.StartSandbox(SandboxBPF::PROCESS_MULTI_THREADED)); |
@@ -2356,46 +2308,39 @@ intptr_t NoOpHandler(const struct arch_seccomp_data& args, void*) { |
return -1; |
} |
-class UnsafeTrapWithCondPolicy : public SandboxBPFPolicy { |
+class UnsafeTrapWithCondPolicy : public SandboxBPFDSLPolicy { |
public: |
UnsafeTrapWithCondPolicy() {} |
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox, |
- int sysno) const OVERRIDE { |
+ virtual ~UnsafeTrapWithCondPolicy() {} |
+ |
+ virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE { |
DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); |
setenv(kSandboxDebuggingEnv, "t", 0); |
Die::SuppressInfoMessages(true); |
if (SandboxBPF::IsRequiredForUnsafeTrap(sysno)) |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ return Allow(); |
switch (sysno) { |
- case __NR_uname: |
- return sandbox->Cond(0, |
- ErrorCode::TP_32BIT, |
- ErrorCode::OP_EQUAL, |
- 0, |
- ErrorCode(ErrorCode::ERR_ALLOWED), |
- ErrorCode(EPERM)); |
- case __NR_setgid: |
- return sandbox->Cond(0, |
- ErrorCode::TP_32BIT, |
- ErrorCode::OP_EQUAL, |
- 100, |
- ErrorCode(ErrorCode(ENOMEM)), |
- sandbox->Cond(0, |
- ErrorCode::TP_32BIT, |
- ErrorCode::OP_EQUAL, |
- 200, |
- ErrorCode(ENOSYS), |
- ErrorCode(EPERM))); |
+ case __NR_uname: { |
+ const Arg<uint32_t> arg(0); |
+ return If(arg == 0, Allow()).Else(Error(EPERM)); |
+ } |
+ case __NR_setgid: { |
+ const Arg<uint32_t> arg(0); |
+ return Switch(arg) |
+ .Case(100, Error(ENOMEM)) |
+ .Case(200, Error(ENOSYS)) |
+ .Default(Error(EPERM)); |
+ } |
case __NR_close: |
case __NR_exit_group: |
case __NR_write: |
- return ErrorCode(ErrorCode::ERR_ALLOWED); |
+ return Allow(); |
case __NR_getppid: |
- return sandbox->UnsafeTrap(NoOpHandler, NULL); |
+ return UnsafeTrap(NoOpHandler, NULL); |
default: |
- return ErrorCode(EPERM); |
+ return Error(EPERM); |
} |
} |
@@ -2422,4 +2367,5 @@ BPF_TEST_C(SandboxBPF, UnsafeTrapWithCond, UnsafeTrapWithCondPolicy) { |
} // namespace |
+} // namespace bpf_dsl |
} // namespace sandbox |