Commit d84f4fc6 authored by Matthew Dempsky's avatar Matthew Dempsky

sandbox: Convert remaining legacy tests to use policy classes

BUG=414363
R=jln@chromium.org

Review URL: https://codereview.chromium.org/588143007

Cr-Commit-Position: refs/heads/master@{#296212}
parent aaa3b662
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include "base/time/time.h" #include "base/time/time.h"
#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h" #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
#include "sandbox/linux/seccomp-bpf/bpf_tests.h" #include "sandbox/linux/seccomp-bpf/bpf_tests.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
#include "sandbox/linux/seccomp-bpf/syscall.h" #include "sandbox/linux/seccomp-bpf/syscall.h"
#include "sandbox/linux/services/linux_syscalls.h" #include "sandbox/linux/services/linux_syscalls.h"
#include "third_party/lss/linux_syscall_support.h" // for MAKE_PROCESS_CPUCLOCK #include "third_party/lss/linux_syscall_support.h" // for MAKE_PROCESS_CPUCLOCK
......
...@@ -153,7 +153,6 @@ component("seccomp_bpf") { ...@@ -153,7 +153,6 @@ component("seccomp_bpf") {
"seccomp-bpf/linux_seccomp.h", "seccomp-bpf/linux_seccomp.h",
"seccomp-bpf/sandbox_bpf.cc", "seccomp-bpf/sandbox_bpf.cc",
"seccomp-bpf/sandbox_bpf.h", "seccomp-bpf/sandbox_bpf.h",
"seccomp-bpf/sandbox_bpf_compatibility_policy.h",
"seccomp-bpf/sandbox_bpf_policy.cc", "seccomp-bpf/sandbox_bpf_policy.cc",
"seccomp-bpf/sandbox_bpf_policy.h", "seccomp-bpf/sandbox_bpf_policy.h",
"seccomp-bpf/syscall.cc", "seccomp-bpf/syscall.cc",
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "sandbox/linux/bpf_dsl/bpf_dsl.h" #include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <pthread.h> #include <pthread.h>
#include <sched.h> #include <sched.h>
#include <signal.h> #include <signal.h>
...@@ -34,6 +35,7 @@ ...@@ -34,6 +35,7 @@
#include "sandbox/linux/seccomp-bpf/bpf_tests.h" #include "sandbox/linux/seccomp-bpf/bpf_tests.h"
#include "sandbox/linux/seccomp-bpf/die.h" #include "sandbox/linux/seccomp-bpf/die.h"
#include "sandbox/linux/seccomp-bpf/linux_seccomp.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/syscall.h"
#include "sandbox/linux/seccomp-bpf/trap.h" #include "sandbox/linux/seccomp-bpf/trap.h"
#include "sandbox/linux/services/broker_process.h" #include "sandbox/linux/services/broker_process.h"
...@@ -107,7 +109,8 @@ intptr_t IncreaseCounter(const struct arch_seccomp_data& args, void* aux) { ...@@ -107,7 +109,8 @@ intptr_t IncreaseCounter(const struct arch_seccomp_data& args, void* aux) {
class VerboseAPITestingPolicy : public SandboxBPFDSLPolicy { class VerboseAPITestingPolicy : public SandboxBPFDSLPolicy {
public: public:
VerboseAPITestingPolicy(int* counter_ptr) : counter_ptr_(counter_ptr) {} explicit VerboseAPITestingPolicy(int* counter_ptr)
: counter_ptr_(counter_ptr) {}
virtual ~VerboseAPITestingPolicy() {} virtual ~VerboseAPITestingPolicy() {}
virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE { virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE {
...@@ -214,21 +217,30 @@ intptr_t EnomemHandler(const struct arch_seccomp_data& args, void* aux) { ...@@ -214,21 +217,30 @@ intptr_t EnomemHandler(const struct arch_seccomp_data& args, void* aux) {
return -ENOMEM; return -ENOMEM;
} }
ErrorCode BlacklistNanosleepPolicySigsys(SandboxBPF* sandbox, class BlacklistNanosleepTrapPolicy : public SandboxBPFDSLPolicy {
int sysno, public:
int* aux) { explicit BlacklistNanosleepTrapPolicy(int* aux) : aux_(aux) {}
DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); virtual ~BlacklistNanosleepTrapPolicy() {}
switch (sysno) {
case __NR_nanosleep: virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE {
return sandbox->Trap(EnomemHandler, aux); DCHECK(SandboxBPF::IsValidSyscallNumber(sysno));
default: switch (sysno) {
return ErrorCode(ErrorCode::ERR_ALLOWED); case __NR_nanosleep:
return Trap(EnomemHandler, aux_);
default:
return Allow();
}
} }
}
private:
int* aux_;
DISALLOW_COPY_AND_ASSIGN(BlacklistNanosleepTrapPolicy);
};
BPF_TEST(SandboxBPF, BPF_TEST(SandboxBPF,
BasicBlacklistWithSigsys, BasicBlacklistWithSigsys,
BlacklistNanosleepPolicySigsys, BlacklistNanosleepTrapPolicy,
int /* (*BPF_AUX) */) { int /* (*BPF_AUX) */) {
// getpid() should work properly // getpid() should work properly
errno = 0; errno = 0;
...@@ -505,26 +517,34 @@ intptr_t CountSyscalls(const struct arch_seccomp_data& args, void* aux) { ...@@ -505,26 +517,34 @@ intptr_t CountSyscalls(const struct arch_seccomp_data& args, void* aux) {
return SandboxBPF::ForwardSyscall(args); return SandboxBPF::ForwardSyscall(args);
} }
ErrorCode GreyListedPolicy(SandboxBPF* sandbox, int sysno, int* aux) { class GreyListedPolicy : public SandboxBPFDSLPolicy {
// Set the global environment for unsafe traps once. public:
if (sysno == MIN_SYSCALL) { explicit GreyListedPolicy(int* aux) : aux_(aux) {
// Set the global environment for unsafe traps once.
EnableUnsafeTraps(); EnableUnsafeTraps();
} }
virtual ~GreyListedPolicy() {}
// Some system calls must always be allowed, if our policy wants to make virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE {
// use of UnsafeTrap() DCHECK(SandboxBPF::IsValidSyscallNumber(sysno));
if (SandboxBPF::IsRequiredForUnsafeTrap(sysno)) { // Some system calls must always be allowed, if our policy wants to make
return ErrorCode(ErrorCode::ERR_ALLOWED); // use of UnsafeTrap()
} else if (sysno == __NR_getpid) { if (SandboxBPF::IsRequiredForUnsafeTrap(sysno)) {
// Disallow getpid() return Allow();
return ErrorCode(EPERM); } else if (sysno == __NR_getpid) {
} else if (SandboxBPF::IsValidSyscallNumber(sysno)) { // Disallow getpid()
// Allow (and count) all other system calls. return Error(EPERM);
return sandbox->UnsafeTrap(CountSyscalls, aux); } else {
} else { // Allow (and count) all other system calls.
return ErrorCode(ENOSYS); return UnsafeTrap(CountSyscalls, aux_);
}
} }
}
private:
int* aux_;
DISALLOW_COPY_AND_ASSIGN(GreyListedPolicy);
};
BPF_TEST(SandboxBPF, GreyListedPolicy, GreyListedPolicy, int /* (*BPF_AUX) */) { BPF_TEST(SandboxBPF, GreyListedPolicy, GreyListedPolicy, int /* (*BPF_AUX) */) {
BPF_ASSERT(syscall(__NR_getpid) == -1); BPF_ASSERT(syscall(__NR_getpid) == -1);
...@@ -784,30 +804,36 @@ intptr_t BrokerOpenTrapHandler(const struct arch_seccomp_data& args, ...@@ -784,30 +804,36 @@ intptr_t BrokerOpenTrapHandler(const struct arch_seccomp_data& args,
} }
} }
ErrorCode DenyOpenPolicy(SandboxBPF* sandbox, class DenyOpenPolicy : public SandboxBPFDSLPolicy {
int sysno, public:
InitializedOpenBroker* iob) { explicit DenyOpenPolicy(InitializedOpenBroker* iob) : iob_(iob) {}
if (!SandboxBPF::IsValidSyscallNumber(sysno)) { virtual ~DenyOpenPolicy() {}
return ErrorCode(ENOSYS);
}
switch (sysno) { virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE {
case __NR_faccessat: DCHECK(SandboxBPF::IsValidSyscallNumber(sysno));
switch (sysno) {
case __NR_faccessat:
#if defined(__NR_access) #if defined(__NR_access)
case __NR_access: case __NR_access:
#endif #endif
#if defined(__NR_open) #if defined(__NR_open)
case __NR_open: case __NR_open:
#endif #endif
case __NR_openat: case __NR_openat:
// We get a InitializedOpenBroker class, but our trap handler wants // We get a InitializedOpenBroker class, but our trap handler wants
// the BrokerProcess object. // the BrokerProcess object.
return ErrorCode( return Trap(BrokerOpenTrapHandler, iob_->broker_process());
sandbox->Trap(BrokerOpenTrapHandler, iob->broker_process())); default:
default: return Allow();
return ErrorCode(ErrorCode::ERR_ALLOWED); }
} }
}
private:
InitializedOpenBroker* iob_;
DISALLOW_COPY_AND_ASSIGN(DenyOpenPolicy);
};
// We use a InitializedOpenBroker class, so that we can run unsandboxed // 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. // code in its constructor, which is the only way to do so in a BPF_TEST.
...@@ -956,20 +982,18 @@ class EqualityStressTest { ...@@ -956,20 +982,18 @@ class EqualityStressTest {
} }
} }
ErrorCode Policy(SandboxBPF* sandbox, int sysno) { ResultExpr Policy(int sysno) {
if (!SandboxBPF::IsValidSyscallNumber(sysno)) { DCHECK(SandboxBPF::IsValidSyscallNumber(sysno));
// FIXME: we should really not have to do that in a trivial policy if (sysno < 0 || sysno >= (int)arg_values_.size() ||
return ErrorCode(ENOSYS); IsReservedSyscall(sysno)) {
} else if (sysno < 0 || sysno >= (int)arg_values_.size() ||
IsReservedSyscall(sysno)) {
// We only return ErrorCode values for the system calls that // We only return ErrorCode values for the system calls that
// are part of our test data. Every other system call remains // are part of our test data. Every other system call remains
// allowed. // allowed.
return ErrorCode(ErrorCode::ERR_ALLOWED); return Allow();
} else { } else {
// ToErrorCode() turns an ArgValue object into an ErrorCode that is // ToErrorCode() turns an ArgValue object into an ErrorCode that is
// suitable for use by a sandbox policy. // suitable for use by a sandbox policy.
return ToErrorCode(sandbox, arg_values_[sysno]); return ToErrorCode(arg_values_[sysno]);
} }
} }
...@@ -1116,42 +1140,38 @@ class EqualityStressTest { ...@@ -1116,42 +1140,38 @@ class EqualityStressTest {
} }
} }
ErrorCode ToErrorCode(SandboxBPF* sandbox, ArgValue* arg_value) { ResultExpr ToErrorCode(ArgValue* arg_value) {
// Compute the ErrorCode that should be returned, if none of our // Compute the ResultExpr that should be returned, if none of our
// tests succeed (i.e. the system call parameter doesn't match any // tests succeed (i.e. the system call parameter doesn't match any
// of the values in arg_value->tests[].k_value). // of the values in arg_value->tests[].k_value).
ErrorCode err; ResultExpr err;
if (arg_value->err) { if (arg_value->err) {
// If this was a leaf node, return the errno value that we expect to // If this was a leaf node, return the errno value that we expect to
// return from the BPF filter program. // return from the BPF filter program.
err = ErrorCode(arg_value->err); err = Error(arg_value->err);
} else { } else {
// If this wasn't a leaf node yet, recursively descend into the rest // 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() // of the tree. This will end up adding a few more SandboxBPF::Cond()
// tests to our ErrorCode. // 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. // Now, iterate over all the test cases that we want to compare against.
// This builds a chain of SandboxBPF::Cond() tests // This builds a chain of SandboxBPF::Cond() tests
// (aka "if ... elif ... elif ... elif ... fi") // (aka "if ... elif ... elif ... elif ... fi")
for (int n = arg_value->size; n-- > 0;) { for (int n = arg_value->size; n-- > 0;) {
ErrorCode matched; ResultExpr matched;
// Again, we distinguish between leaf nodes and subtrees. // Again, we distinguish between leaf nodes and subtrees.
if (arg_value->tests[n].err) { if (arg_value->tests[n].err) {
matched = ErrorCode(arg_value->tests[n].err); matched = Error(arg_value->tests[n].err);
} else { } 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. // For now, all of our tests are limited to 32bit.
// We have separate tests that check the behavior of 32bit vs. 64bit // We have separate tests that check the behavior of 32bit vs. 64bit
// conditional expressions. // conditional expressions.
err = sandbox->Cond(arg_value->argno, const Arg<uint32_t> arg(arg_value->argno);
ErrorCode::TP_32BIT, err = If(arg == arg_value->tests[n].k_value, matched).Else(err);
ErrorCode::OP_EQUAL,
arg_value->tests[n].k_value,
matched,
err);
} }
return err; return err;
} }
...@@ -1221,12 +1241,20 @@ class EqualityStressTest { ...@@ -1221,12 +1241,20 @@ class EqualityStressTest {
static const int kMaxArgs = 6; static const int kMaxArgs = 6;
}; };
ErrorCode EqualityStressTestPolicy(SandboxBPF* sandbox, class EqualityStressTestPolicy : public SandboxBPFDSLPolicy {
int sysno, public:
EqualityStressTest* aux) { explicit EqualityStressTestPolicy(EqualityStressTest* aux) : aux_(aux) {}
DCHECK(aux); virtual ~EqualityStressTestPolicy() {}
return aux->Policy(sandbox, sysno);
} virtual ResultExpr EvaluateSyscall(int sysno) const OVERRIDE {
return aux_->Policy(sysno);
}
private:
EqualityStressTest* aux_;
DISALLOW_COPY_AND_ASSIGN(EqualityStressTestPolicy);
};
BPF_TEST(SandboxBPF, BPF_TEST(SandboxBPF,
EqualityTests, EqualityTests,
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "sandbox/linux/bpf_dsl/bpf_dsl.h" #include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/syscall.h> #include <sys/syscall.h>
......
...@@ -133,7 +133,6 @@ ...@@ -133,7 +133,6 @@
'seccomp-bpf/linux_seccomp.h', 'seccomp-bpf/linux_seccomp.h',
'seccomp-bpf/sandbox_bpf.cc', 'seccomp-bpf/sandbox_bpf.cc',
'seccomp-bpf/sandbox_bpf.h', 'seccomp-bpf/sandbox_bpf.h',
'seccomp-bpf/sandbox_bpf_compatibility_policy.h',
'seccomp-bpf/sandbox_bpf_policy.cc', 'seccomp-bpf/sandbox_bpf_policy.cc',
'seccomp-bpf/sandbox_bpf_policy.h', 'seccomp-bpf/sandbox_bpf_policy.h',
'seccomp-bpf/syscall.cc', 'seccomp-bpf/syscall.cc',
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "sandbox/linux/seccomp-bpf-helpers/baseline_policy.h" #include "sandbox/linux/seccomp-bpf-helpers/baseline_policy.h"
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <linux/futex.h> #include <linux/futex.h>
#include <sched.h> #include <sched.h>
#include <signal.h> #include <signal.h>
......
...@@ -5,15 +5,8 @@ ...@@ -5,15 +5,8 @@
#ifndef SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTER_COMPATIBILITY_DELEGATE_H_ #ifndef SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTER_COMPATIBILITY_DELEGATE_H_
#define SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTER_COMPATIBILITY_DELEGATE_H_ #define SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTER_COMPATIBILITY_DELEGATE_H_
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf_compatibility_policy.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.h" #include "sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.h"
#include "sandbox/linux/tests/sandbox_test_runner.h"
#include "sandbox/linux/tests/unit_tests.h"
namespace sandbox { namespace sandbox {
...@@ -24,16 +17,13 @@ namespace sandbox { ...@@ -24,16 +17,13 @@ namespace sandbox {
// This allows both the policy and the test function to take a pointer to an // This allows both the policy and the test function to take a pointer to an
// object of type "Aux" as a parameter. This is used to implement the BPF_TEST // object of type "Aux" as a parameter. This is used to implement the BPF_TEST
// macro and should generally not be used directly. // macro and should generally not be used directly.
template <class Aux> template <class Policy, class Aux>
class BPFTesterCompatibilityDelegate : public BPFTesterDelegate { class BPFTesterCompatibilityDelegate : public BPFTesterDelegate {
public: public:
typedef Aux AuxType; typedef void (*TestFunction)(Aux*);
BPFTesterCompatibilityDelegate(
void (*test_function)(AuxType*), explicit BPFTesterCompatibilityDelegate(TestFunction test_function)
typename CompatibilityPolicy<AuxType>::SyscallEvaluator policy_function) : aux_(), test_function_(test_function) {}
: aux_(),
test_function_(test_function),
policy_function_(policy_function) {}
virtual ~BPFTesterCompatibilityDelegate() {} virtual ~BPFTesterCompatibilityDelegate() {}
...@@ -42,8 +32,7 @@ class BPFTesterCompatibilityDelegate : public BPFTesterDelegate { ...@@ -42,8 +32,7 @@ class BPFTesterCompatibilityDelegate : public BPFTesterDelegate {
// running the test. In this process, the current object is guaranteed // running the test. In this process, the current object is guaranteed
// to live forever. So it's ok to pass aux_pointer_for_policy_ to // to live forever. So it's ok to pass aux_pointer_for_policy_ to
// the policy, which could in turn pass it to the kernel via Trap(). // the policy, which could in turn pass it to the kernel via Trap().
return scoped_ptr<SandboxBPFPolicy>( return scoped_ptr<SandboxBPFPolicy>(new Policy(&aux_));
new CompatibilityPolicy<AuxType>(policy_function_, &aux_));
} }
virtual void RunTestFunction() OVERRIDE { virtual void RunTestFunction() OVERRIDE {
...@@ -54,9 +43,9 @@ class BPFTesterCompatibilityDelegate : public BPFTesterDelegate { ...@@ -54,9 +43,9 @@ class BPFTesterCompatibilityDelegate : public BPFTesterDelegate {
} }
private: private:
AuxType aux_; Aux aux_;
void (*test_function_)(AuxType*); TestFunction test_function_;
typename CompatibilityPolicy<AuxType>::SyscallEvaluator policy_function_;
DISALLOW_COPY_AND_ASSIGN(BPFTesterCompatibilityDelegate); DISALLOW_COPY_AND_ASSIGN(BPFTesterCompatibilityDelegate);
}; };
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTS_H__ #ifndef SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTS_H__
#define SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTS_H__ #define SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTS_H__
#include "base/logging.h"
#include "base/macros.h" #include "base/macros.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h" #include "sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h"
...@@ -66,34 +67,31 @@ namespace sandbox { ...@@ -66,34 +67,31 @@ namespace sandbox {
// This form of BPF_TEST is now discouraged (but still allowed) in favor of // This form of BPF_TEST is now discouraged (but still allowed) in favor of
// BPF_TEST_D and BPF_TEST_C. // BPF_TEST_D and BPF_TEST_C.
// The |policy| parameter should be a SyscallEvaluator function pointer // The |policy| parameter should be a SandboxBPFPolicy subclass.
// (which is now a deprecated way of expressing policies). // BPF_TEST() takes a C++ data type as an fourth parameter. A variable
// BPF_TEST() takes a C++ data type as an optional fourth parameter. If // of this type will be allocated and a pointer to it will be
// present, this sets up a variable that can be accessed as "BPF_AUX". This // available within the test function as "BPF_AUX". The pointer will
// variable will be passed as an argument to the "policy" function. Policies // also be passed as an argument to the policy's constructor. Policies
// would typically use it as an argument to SandboxBPF::Trap(), if they want to // would typically use it as an argument to SandboxBPF::Trap(), if
// communicate data between the BPF_TEST() and a Trap() function. The life-time // they want to communicate data between the BPF_TEST() and a Trap()
// of this object is the same as the life-time of the process running under the // function. The life-time of this object is the same as the life-time
// seccomp-bpf policy. // of the process running under the seccomp-bpf policy.
// The type specified in |aux| and the last parameter of the policy function // |aux| must not be void.
// must be compatible. |aux| must not be void.
#define BPF_TEST(test_case_name, test_name, policy, aux) \ #define BPF_TEST(test_case_name, test_name, policy, aux) \
BPF_DEATH_TEST(test_case_name, test_name, DEATH_SUCCESS(), policy, aux) BPF_DEATH_TEST(test_case_name, test_name, DEATH_SUCCESS(), policy, aux)
// A BPF_DEATH_TEST is just the same as a BPF_TEST, but it assumes that the // A BPF_DEATH_TEST is just the same as a BPF_TEST, but it assumes that the
// test will fail with a particular known error condition. Use the DEATH_XXX() // test will fail with a particular known error condition. Use the DEATH_XXX()
// macros from unit_tests.h to specify the expected error condition. // macros from unit_tests.h to specify the expected error condition.
#define BPF_DEATH_TEST(test_case_name, test_name, death, policy, aux) \ #define BPF_DEATH_TEST(test_case_name, test_name, death, policy, aux) \
void BPF_TEST_##test_name( \ void BPF_TEST_##test_name(aux* BPF_AUX); \
sandbox::BPFTesterCompatibilityDelegate<aux>::AuxType* BPF_AUX); \ TEST(test_case_name, DISABLE_ON_TSAN(test_name)) { \
TEST(test_case_name, DISABLE_ON_TSAN(test_name)) { \ sandbox::SandboxBPFTestRunner bpf_test_runner( \
sandbox::SandboxBPFTestRunner bpf_test_runner( \ new sandbox::BPFTesterCompatibilityDelegate<policy, aux>( \
new sandbox::BPFTesterCompatibilityDelegate<aux>(BPF_TEST_##test_name, \ BPF_TEST_##test_name)); \
policy)); \ sandbox::UnitTests::RunTestInProcess(&bpf_test_runner, death); \
sandbox::UnitTests::RunTestInProcess(&bpf_test_runner, death); \ } \
} \ void BPF_TEST_##test_name(aux* BPF_AUX)
void BPF_TEST_##test_name( \
sandbox::BPFTesterCompatibilityDelegate<aux>::AuxType* BPF_AUX)
// This class takes a simple function pointer as a constructor parameter and a // This class takes a simple function pointer as a constructor parameter and a
// class name as a template parameter to implement the BPFTesterDelegate // class name as a template parameter to implement the BPFTesterDelegate
......
...@@ -33,22 +33,24 @@ class FourtyTwo { ...@@ -33,22 +33,24 @@ class FourtyTwo {
DISALLOW_COPY_AND_ASSIGN(FourtyTwo); DISALLOW_COPY_AND_ASSIGN(FourtyTwo);
}; };
ErrorCode EmptyPolicyTakesClass(SandboxBPF* sandbox, class EmptyClassTakingPolicy : public SandboxBPFPolicy {
int sysno, public:
FourtyTwo* fourty_two) { explicit EmptyClassTakingPolicy(FourtyTwo* fourty_two) {
// |aux| should point to an instance of FourtyTwo. BPF_ASSERT(fourty_two);
BPF_ASSERT(fourty_two); BPF_ASSERT(FourtyTwo::kMagicValue == fourty_two->value());
BPF_ASSERT(FourtyTwo::kMagicValue == fourty_two->value()); }
if (!SandboxBPF::IsValidSyscallNumber(sysno)) { virtual ~EmptyClassTakingPolicy() {}
return ErrorCode(ENOSYS);
} else { virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox,
int sysno) const OVERRIDE {
DCHECK(SandboxBPF::IsValidSyscallNumber(sysno));
return ErrorCode(ErrorCode::ERR_ALLOWED); return ErrorCode(ErrorCode::ERR_ALLOWED);
} }
} };
BPF_TEST(BPFTest, BPF_TEST(BPFTest,
BPFAUXPointsToClass, BPFAUXPointsToClass,
EmptyPolicyTakesClass, EmptyClassTakingPolicy,
FourtyTwo /* *BPF_AUX */) { FourtyTwo /* *BPF_AUX */) {
// BPF_AUX should point to an instance of FourtyTwo. // BPF_AUX should point to an instance of FourtyTwo.
BPF_ASSERT(BPF_AUX); BPF_ASSERT(BPF_AUX);
...@@ -62,14 +64,14 @@ TEST(BPFTest, BPFTesterCompatibilityDelegateLeakTest) { ...@@ -62,14 +64,14 @@ TEST(BPFTest, BPFTesterCompatibilityDelegateLeakTest) {
// Don't do anything, simply gives dynamic tools an opportunity to detect // Don't do anything, simply gives dynamic tools an opportunity to detect
// leaks. // leaks.
{ {
BPFTesterCompatibilityDelegate<FourtyTwo> simple_delegate( BPFTesterCompatibilityDelegate<EmptyClassTakingPolicy, FourtyTwo>
DummyTestFunction, EmptyPolicyTakesClass); simple_delegate(DummyTestFunction);
} }
{ {
// Test polymorphism. // Test polymorphism.
scoped_ptr<BPFTesterDelegate> simple_delegate( scoped_ptr<BPFTesterDelegate> simple_delegate(
new BPFTesterCompatibilityDelegate<FourtyTwo>(DummyTestFunction, new BPFTesterCompatibilityDelegate<EmptyClassTakingPolicy, FourtyTwo>(
EmptyPolicyTakesClass)); DummyTestFunction));
} }
} }
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_COMPATIBILITY_POLICY_H_
#define SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_COMPATIBILITY_POLICY_H_
#include "base/logging.h"
#include "base/macros.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
namespace sandbox {
// This class allows compatibility with the old, deprecated
// policies that were designed for SetSandboxPolicyDeprecated().
template <class AuxType>
class CompatibilityPolicy : public SandboxBPFPolicy {
public:
typedef ErrorCode (*SyscallEvaluator)(SandboxBPF* sandbox_compiler,
int system_call_number,
AuxType* aux);
CompatibilityPolicy(SyscallEvaluator syscall_evaluator, AuxType* aux)
: syscall_evaluator_(syscall_evaluator), aux_(aux) {}
virtual ~CompatibilityPolicy() {}
virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
int system_call_number) const OVERRIDE {
DCHECK(SandboxBPF::IsValidSyscallNumber(system_call_number));
return syscall_evaluator_(sandbox_compiler, system_call_number, aux_);
}
private:
SyscallEvaluator syscall_evaluator_;
AuxType* aux_;
DISALLOW_COPY_AND_ASSIGN(CompatibilityPolicy);
};
} // namespace sandbox
#endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_COMPATIBILITY_POLICY_H_
...@@ -99,18 +99,26 @@ intptr_t CopySyscallArgsToAux(const struct arch_seccomp_data& args, void* aux) { ...@@ -99,18 +99,26 @@ intptr_t CopySyscallArgsToAux(const struct arch_seccomp_data& args, void* aux) {
return -ENOMEM; return -ENOMEM;
} }
ErrorCode CopyAllArgsOnUnamePolicy(SandboxBPF* sandbox, class CopyAllArgsOnUnamePolicy : public SandboxBPFPolicy {
int sysno, public:
std::vector<uint64_t>* aux) { explicit CopyAllArgsOnUnamePolicy(std::vector<uint64_t>* aux) : aux_(aux) {}
if (!SandboxBPF::IsValidSyscallNumber(sysno)) { virtual ~CopyAllArgsOnUnamePolicy() {}
return ErrorCode(ENOSYS);
virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox,
int sysno) const OVERRIDE {
DCHECK(SandboxBPF::IsValidSyscallNumber(sysno));
if (sysno == __NR_uname) {
return sandbox->Trap(CopySyscallArgsToAux, aux_);
} else {
return ErrorCode(ErrorCode::ERR_ALLOWED);
}
} }
if (sysno == __NR_uname) {
return sandbox->Trap(CopySyscallArgsToAux, aux); private:
} else { std::vector<uint64_t>* aux_;
return ErrorCode(ErrorCode::ERR_ALLOWED);
} DISALLOW_COPY_AND_ASSIGN(CopyAllArgsOnUnamePolicy);
} };
// We are testing Syscall::Call() by making use of a BPF filter that // We are testing Syscall::Call() by making use of a BPF filter that
// allows us // allows us
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment