| Index: sandbox/linux/bpf_dsl/bpf_dsl_more_unittest.cc
|
| diff --git a/sandbox/linux/bpf_dsl/bpf_dsl_more_unittest.cc b/sandbox/linux/bpf_dsl/bpf_dsl_more_unittest.cc
|
| index 667dfb218bfae7bfc8ac8f7fce9c652a38db0b63..b7fbe99bbe5c72c850ccc6b43d03614dca683d3d 100644
|
| --- a/sandbox/linux/bpf_dsl/bpf_dsl_more_unittest.cc
|
| +++ b/sandbox/linux/bpf_dsl/bpf_dsl_more_unittest.cc
|
| @@ -5,6 +5,7 @@
|
| #include "sandbox/linux/bpf_dsl/bpf_dsl.h"
|
|
|
| #include <errno.h>
|
| +#include <fcntl.h>
|
| #include <pthread.h>
|
| #include <sched.h>
|
| #include <signal.h>
|
| @@ -34,6 +35,7 @@
|
| #include "sandbox/linux/seccomp-bpf/bpf_tests.h"
|
| #include "sandbox/linux/seccomp-bpf/die.h"
|
| #include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
|
| +#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
|
| #include "sandbox/linux/seccomp-bpf/syscall.h"
|
| #include "sandbox/linux/seccomp-bpf/trap.h"
|
| #include "sandbox/linux/services/broker_process.h"
|
| @@ -107,7 +109,8 @@ intptr_t IncreaseCounter(const struct arch_seccomp_data& args, void* aux) {
|
|
|
| class VerboseAPITestingPolicy : public SandboxBPFDSLPolicy {
|
| public:
|
| - VerboseAPITestingPolicy(int* counter_ptr) : counter_ptr_(counter_ptr) {}
|
| + explicit VerboseAPITestingPolicy(int* counter_ptr)
|
| + : counter_ptr_(counter_ptr) {}
|
| virtual ~VerboseAPITestingPolicy() {}
|
|
|
| virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE {
|
| @@ -214,21 +217,30 @@ intptr_t EnomemHandler(const struct arch_seccomp_data& args, void* aux) {
|
| return -ENOMEM;
|
| }
|
|
|
| -ErrorCode BlacklistNanosleepPolicySigsys(SandboxBPF* sandbox,
|
| - int sysno,
|
| - int* aux) {
|
| - DCHECK(SandboxBPF::IsValidSyscallNumber(sysno));
|
| - switch (sysno) {
|
| - case __NR_nanosleep:
|
| - return sandbox->Trap(EnomemHandler, aux);
|
| - default:
|
| - return ErrorCode(ErrorCode::ERR_ALLOWED);
|
| +class BlacklistNanosleepTrapPolicy : public SandboxBPFDSLPolicy {
|
| + public:
|
| + explicit BlacklistNanosleepTrapPolicy(int* aux) : aux_(aux) {}
|
| + virtual ~BlacklistNanosleepTrapPolicy() {}
|
| +
|
| + virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE {
|
| + DCHECK(SandboxBPF::IsValidSyscallNumber(sysno));
|
| + switch (sysno) {
|
| + case __NR_nanosleep:
|
| + return Trap(EnomemHandler, aux_);
|
| + default:
|
| + return Allow();
|
| + }
|
| }
|
| -}
|
| +
|
| + private:
|
| + int* aux_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(BlacklistNanosleepTrapPolicy);
|
| +};
|
|
|
| BPF_TEST(SandboxBPF,
|
| BasicBlacklistWithSigsys,
|
| - BlacklistNanosleepPolicySigsys,
|
| + BlacklistNanosleepTrapPolicy,
|
| int /* (*BPF_AUX) */) {
|
| // getpid() should work properly
|
| errno = 0;
|
| @@ -505,26 +517,34 @@ intptr_t CountSyscalls(const struct arch_seccomp_data& args, void* aux) {
|
| return SandboxBPF::ForwardSyscall(args);
|
| }
|
|
|
| -ErrorCode GreyListedPolicy(SandboxBPF* sandbox, int sysno, int* aux) {
|
| - // Set the global environment for unsafe traps once.
|
| - if (sysno == MIN_SYSCALL) {
|
| +class GreyListedPolicy : public SandboxBPFDSLPolicy {
|
| + public:
|
| + explicit GreyListedPolicy(int* aux) : aux_(aux) {
|
| + // Set the global environment for unsafe traps once.
|
| EnableUnsafeTraps();
|
| }
|
| + virtual ~GreyListedPolicy() {}
|
|
|
| - // 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);
|
| - } else if (sysno == __NR_getpid) {
|
| - // Disallow getpid()
|
| - return ErrorCode(EPERM);
|
| - } else if (SandboxBPF::IsValidSyscallNumber(sysno)) {
|
| - // Allow (and count) all other system calls.
|
| - return sandbox->UnsafeTrap(CountSyscalls, aux);
|
| - } else {
|
| - return ErrorCode(ENOSYS);
|
| + virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE {
|
| + DCHECK(SandboxBPF::IsValidSyscallNumber(sysno));
|
| + // Some system calls must always be allowed, if our policy wants to make
|
| + // use of UnsafeTrap()
|
| + if (SandboxBPF::IsRequiredForUnsafeTrap(sysno)) {
|
| + return Allow();
|
| + } else if (sysno == __NR_getpid) {
|
| + // Disallow getpid()
|
| + return Error(EPERM);
|
| + } else {
|
| + // Allow (and count) all other system calls.
|
| + return UnsafeTrap(CountSyscalls, aux_);
|
| + }
|
| }
|
| -}
|
| +
|
| + private:
|
| + int* aux_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(GreyListedPolicy);
|
| +};
|
|
|
| BPF_TEST(SandboxBPF, GreyListedPolicy, GreyListedPolicy, int /* (*BPF_AUX) */) {
|
| BPF_ASSERT(syscall(__NR_getpid) == -1);
|
| @@ -784,30 +804,36 @@ intptr_t BrokerOpenTrapHandler(const struct arch_seccomp_data& args,
|
| }
|
| }
|
|
|
| -ErrorCode DenyOpenPolicy(SandboxBPF* sandbox,
|
| - int sysno,
|
| - InitializedOpenBroker* iob) {
|
| - if (!SandboxBPF::IsValidSyscallNumber(sysno)) {
|
| - return ErrorCode(ENOSYS);
|
| - }
|
| +class DenyOpenPolicy : public SandboxBPFDSLPolicy {
|
| + public:
|
| + explicit DenyOpenPolicy(InitializedOpenBroker* iob) : iob_(iob) {}
|
| + virtual ~DenyOpenPolicy() {}
|
|
|
| - switch (sysno) {
|
| - case __NR_faccessat:
|
| + virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE {
|
| + DCHECK(SandboxBPF::IsValidSyscallNumber(sysno));
|
| +
|
| + switch (sysno) {
|
| + case __NR_faccessat:
|
| #if defined(__NR_access)
|
| - case __NR_access:
|
| + case __NR_access:
|
| #endif
|
| #if defined(__NR_open)
|
| - case __NR_open:
|
| + case __NR_open:
|
| #endif
|
| - case __NR_openat:
|
| - // We get a InitializedOpenBroker class, but our trap handler wants
|
| - // the BrokerProcess object.
|
| - return ErrorCode(
|
| - sandbox->Trap(BrokerOpenTrapHandler, iob->broker_process()));
|
| - default:
|
| - return ErrorCode(ErrorCode::ERR_ALLOWED);
|
| + case __NR_openat:
|
| + // We get a InitializedOpenBroker class, but our trap handler wants
|
| + // the BrokerProcess object.
|
| + return Trap(BrokerOpenTrapHandler, iob_->broker_process());
|
| + default:
|
| + return Allow();
|
| + }
|
| }
|
| -}
|
| +
|
| + private:
|
| + InitializedOpenBroker* iob_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(DenyOpenPolicy);
|
| +};
|
|
|
| // We use a InitializedOpenBroker class, so that we can run unsandboxed
|
| // code in its constructor, which is the only way to do so in a BPF_TEST.
|
| @@ -956,20 +982,18 @@ class EqualityStressTest {
|
| }
|
| }
|
|
|
| - ErrorCode Policy(SandboxBPF* sandbox, int sysno) {
|
| - if (!SandboxBPF::IsValidSyscallNumber(sysno)) {
|
| - // FIXME: we should really not have to do that in a trivial policy
|
| - return ErrorCode(ENOSYS);
|
| - } else if (sysno < 0 || sysno >= (int)arg_values_.size() ||
|
| - IsReservedSyscall(sysno)) {
|
| + ResultExpr Policy(int sysno) {
|
| + DCHECK(SandboxBPF::IsValidSyscallNumber(sysno));
|
| + if (sysno < 0 || sysno >= (int)arg_values_.size() ||
|
| + IsReservedSyscall(sysno)) {
|
| // We only return ErrorCode values for the system calls that
|
| // are part of our test data. Every other system call remains
|
| // allowed.
|
| - return ErrorCode(ErrorCode::ERR_ALLOWED);
|
| + return Allow();
|
| } else {
|
| // ToErrorCode() turns an ArgValue object into an ErrorCode that is
|
| // suitable for use by a sandbox policy.
|
| - return ToErrorCode(sandbox, arg_values_[sysno]);
|
| + return ToErrorCode(arg_values_[sysno]);
|
| }
|
| }
|
|
|
| @@ -1116,42 +1140,38 @@ class EqualityStressTest {
|
| }
|
| }
|
|
|
| - ErrorCode ToErrorCode(SandboxBPF* sandbox, ArgValue* arg_value) {
|
| - // Compute the ErrorCode that should be returned, if none of our
|
| + ResultExpr ToErrorCode(ArgValue* arg_value) {
|
| + // Compute the ResultExpr that should be returned, if none of our
|
| // tests succeed (i.e. the system call parameter doesn't match any
|
| // of the values in arg_value->tests[].k_value).
|
| - ErrorCode err;
|
| + ResultExpr err;
|
| if (arg_value->err) {
|
| // If this was a leaf node, return the errno value that we expect to
|
| // return from the BPF filter program.
|
| - err = ErrorCode(arg_value->err);
|
| + err = Error(arg_value->err);
|
| } else {
|
| // If this wasn't a leaf node yet, recursively descend into the rest
|
| // of the tree. This will end up adding a few more SandboxBPF::Cond()
|
| // tests to our ErrorCode.
|
| - err = ToErrorCode(sandbox, arg_value->arg_value);
|
| + err = ToErrorCode(arg_value->arg_value);
|
| }
|
|
|
| // Now, iterate over all the test cases that we want to compare against.
|
| // This builds a chain of SandboxBPF::Cond() tests
|
| // (aka "if ... elif ... elif ... elif ... fi")
|
| for (int n = arg_value->size; n-- > 0;) {
|
| - ErrorCode matched;
|
| + ResultExpr matched;
|
| // Again, we distinguish between leaf nodes and subtrees.
|
| if (arg_value->tests[n].err) {
|
| - matched = ErrorCode(arg_value->tests[n].err);
|
| + matched = Error(arg_value->tests[n].err);
|
| } else {
|
| - matched = ToErrorCode(sandbox, arg_value->tests[n].arg_value);
|
| + matched = ToErrorCode(arg_value->tests[n].arg_value);
|
| }
|
| // For now, all of our tests are limited to 32bit.
|
| // We have separate tests that check the behavior of 32bit vs. 64bit
|
| // conditional expressions.
|
| - err = sandbox->Cond(arg_value->argno,
|
| - ErrorCode::TP_32BIT,
|
| - ErrorCode::OP_EQUAL,
|
| - arg_value->tests[n].k_value,
|
| - matched,
|
| - err);
|
| + const Arg<uint32_t> arg(arg_value->argno);
|
| + err = If(arg == arg_value->tests[n].k_value, matched).Else(err);
|
| }
|
| return err;
|
| }
|
| @@ -1221,12 +1241,20 @@ class EqualityStressTest {
|
| static const int kMaxArgs = 6;
|
| };
|
|
|
| -ErrorCode EqualityStressTestPolicy(SandboxBPF* sandbox,
|
| - int sysno,
|
| - EqualityStressTest* aux) {
|
| - DCHECK(aux);
|
| - return aux->Policy(sandbox, sysno);
|
| -}
|
| +class EqualityStressTestPolicy : public SandboxBPFDSLPolicy {
|
| + public:
|
| + explicit EqualityStressTestPolicy(EqualityStressTest* aux) : aux_(aux) {}
|
| + virtual ~EqualityStressTestPolicy() {}
|
| +
|
| + virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE {
|
| + return aux_->Policy(sysno);
|
| + }
|
| +
|
| + private:
|
| + EqualityStressTest* aux_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(EqualityStressTestPolicy);
|
| +};
|
|
|
| BPF_TEST(SandboxBPF,
|
| EqualityTests,
|
|
|