Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(529)

Unified Diff: sandbox/linux/bpf_dsl/bpf_dsl_more_unittest.cc

Issue 559653004: Convert sandbox_bpf_unittest.cc to use bpf_dsl (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Sync to master Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698