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

Side by Side Diff: sandbox/linux/seccomp-bpf/bpf_tests.h

Issue 269303002: Linux sandbox: implement new BPF testing macros (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Make sure that policies are created and destroyed in the same process. Created 6 years, 7 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTS_H__ 5 #ifndef SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTS_H__
6 #define SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTS_H__ 6 #define SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTS_H__
7 7
8 #include <fcntl.h> 8 #include "base/basictypes.h"
9 #include <sys/stat.h>
10 #include <sys/types.h>
11
12 #include "base/debug/leak_annotations.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "build/build_config.h" 9 #include "build/build_config.h"
15 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" 10 #include "sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h"
16 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_compatibility_policy.h"
17 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.h"
18 #include "sandbox/linux/tests/sandbox_test_runner.h"
19 #include "sandbox/linux/tests/unit_tests.h" 11 #include "sandbox/linux/tests/unit_tests.h"
20 12
21 namespace sandbox { 13 namespace sandbox {
22 14
23 // A BPF_DEATH_TEST is just the same as a BPF_TEST, but it assumes that the 15 // BPF_TEST_C() is a special version of SANDBOX_TEST(). It runs a test function
24 // test will fail with a particular known error condition. Use the DEATH_XXX() 16 // in a sub-process, under a seccomp-bpf policy specified in
25 // macros from unit_tests.h to specify the expected error condition. 17 // |bpf_policy_class_name| without failing on configurations that are allowed
26 // A BPF_DEATH_TEST is always disabled under ThreadSanitizer, see 18 // to not support seccomp-bpf in their kernels.
27 // crbug.com/243968. 19 // This is the preferred format for new BPF tests. |bpf_policy_class_name| is a
28 #define BPF_DEATH_TEST(test_case_name, test_name, death, policy, aux...) \ 20 // class name (which will be default-constructed) that implements the
29 void BPF_TEST_##test_name( \ 21 // SandboxBPFPolicy interface.
30 sandbox::BPFTesterSimpleDelegate<aux>::AuxType* BPF_AUX); \ 22 // The test function's body can simply follow. Test functions should use
31 TEST(test_case_name, DISABLE_ON_TSAN(test_name)) { \ 23 // the BPF_ASSERT macros defined below, not GTEST's macros. The use of
32 sandbox::SandboxBPFTestRunner bpf_test_runner( \ 24 // CHECK* macros is supported but less robust.
33 new sandbox::BPFTesterSimpleDelegate<aux>(BPF_TEST_##test_name, \ 25 #define BPF_TEST_C(test_case_name, test_name, bpf_policy_class_name) \
34 policy)); \ 26 BPF_DEATH_TEST_C( \
35 sandbox::UnitTests::RunTestInProcess(&bpf_test_runner, death); \ 27 test_case_name, test_name, DEATH_SUCCESS(), bpf_policy_class_name)
36 } \
37 void BPF_TEST_##test_name( \
38 sandbox::BPFTesterSimpleDelegate<aux>::AuxType* BPF_AUX)
39 28
40 // BPF_TEST() is a special version of SANDBOX_TEST(). It turns into a no-op, 29 // Identical to BPF_TEST_C but allows to specify the nature of death.
41 // if the host does not have kernel support for running BPF filters. 30 #define BPF_DEATH_TEST_C( \
42 // Also, it takes advantage of the Die class to avoid calling LOG(FATAL), from 31 test_case_name, test_name, death, bpf_policy_class_name) \
43 // inside our tests, as we don't need or even want all the error handling that 32 void BPF_TEST_C_##test_name(); \
44 // LOG(FATAL) would do. 33 TEST(test_case_name, DISABLE_ON_TSAN(test_name)) { \
45 // BPF_TEST() takes a C++ data type as an optional fourth parameter. If 34 sandbox::SandboxBPFTestRunner bpf_test_runner( \
46 // present, this sets up a variable that can be accessed as "BPF_AUX". This 35 new BPFTesterSimpleDelegate<bpf_policy_class_name>( \
47 // variable will be passed as an argument to the "policy" function. Policies 36 BPF_TEST_C_##test_name)); \
48 // would typically use it as an argument to SandboxBPF::Trap(), if they want to 37 sandbox::UnitTests::RunTestInProcess(&bpf_test_runner, death); \
49 // communicate data between the BPF_TEST() and a Trap() function. The life-time 38 } \
50 // of this object is the same as the life-time of the process. 39 void BPF_TEST_C_##test_name()
51 // The type specified in |aux| and the last parameter of the policy function 40
52 // must be compatible. If |aux| is not specified, the policy function must 41 // This form of BPF_TEST is a little verbose and should be reserved for complex
53 // take a void* as its last parameter (that is, must have the EvaluateSyscall 42 // tests where a lot of control is required.
54 // type). 43 // |bpf_tester_delegate_class| must be a classname implementing the
55 #define BPF_TEST(test_case_name, test_name, policy, aux...) \ 44 // BPFTesterDelegate interface.
56 BPF_DEATH_TEST(test_case_name, test_name, DEATH_SUCCESS(), policy, aux) 45 #define BPF_TEST_D(test_case_name, test_name, bpf_tester_delegate_class) \
46 BPF_DEATH_TEST_D( \
47 test_case_name, test_name, DEATH_SUCCESS(), bpf_tester_delegate_class)
48
49 // Identical to BPF_TEST_D but allows to specify the nature of death.
50 #define BPF_DEATH_TEST_D( \
51 test_case_name, test_name, death, bpf_tester_delegate_class) \
52 TEST(test_case_name, DISABLE_ON_TSAN(test_name)) { \
53 sandbox::SandboxBPFTestRunner bpf_test_runner( \
54 new bpf_tester_delegate_class()); \
55 sandbox::UnitTests::RunTestInProcess(&bpf_test_runner, death); \
56 }
57 57
58 // Assertions are handled exactly the same as with a normal SANDBOX_TEST() 58 // Assertions are handled exactly the same as with a normal SANDBOX_TEST()
59 #define BPF_ASSERT SANDBOX_ASSERT 59 #define BPF_ASSERT SANDBOX_ASSERT
60 #define BPF_ASSERT_EQ(x, y) BPF_ASSERT((x) == (y)) 60 #define BPF_ASSERT_EQ(x, y) BPF_ASSERT((x) == (y))
61 #define BPF_ASSERT_NE(x, y) BPF_ASSERT((x) != (y)) 61 #define BPF_ASSERT_NE(x, y) BPF_ASSERT((x) != (y))
62 #define BPF_ASSERT_LT(x, y) BPF_ASSERT((x) < (y)) 62 #define BPF_ASSERT_LT(x, y) BPF_ASSERT((x) < (y))
63 #define BPF_ASSERT_GT(x, y) BPF_ASSERT((x) > (y)) 63 #define BPF_ASSERT_GT(x, y) BPF_ASSERT((x) > (y))
64 #define BPF_ASSERT_LE(x, y) BPF_ASSERT((x) <= (y)) 64 #define BPF_ASSERT_LE(x, y) BPF_ASSERT((x) <= (y))
65 #define BPF_ASSERT_GE(x, y) BPF_ASSERT((x) >= (y)) 65 #define BPF_ASSERT_GE(x, y) BPF_ASSERT((x) >= (y))
66 66
67 template <class Aux = void> 67 // This form of BPF_TEST is now discouraged (but still allowed) in favor of
68 // BPF_TEST_D and BPF_TEST_C.
69 // The |policy| parameter should be a SyscallEvaluator function pointer
70 // (which is now a deprecated way of expressing policies).
71 // BPF_TEST() takes a C++ data type as an optional fourth parameter. If
72 // present, this sets up a variable that can be accessed as "BPF_AUX". This
73 // variable will be passed as an argument to the "policy" function. Policies
74 // would typically use it as an argument to SandboxBPF::Trap(), if they want to
75 // communicate data between the BPF_TEST() and a Trap() function. The life-time
76 // of this object is the same as the life-time of the process running under the
77 // seccomp-bpf policy.
78 // The type specified in |aux| and the last parameter of the policy function
79 // must be compatible. If |aux| is not specified, the policy function must
80 // take a void* as its last parameter (that is, must have the EvaluateSyscall
81 // type).
82 #define BPF_TEST(test_case_name, test_name, policy, aux...) \
83 BPF_DEATH_TEST(test_case_name, test_name, DEATH_SUCCESS(), policy, aux)
84
85 // A BPF_DEATH_TEST is just the same as a BPF_TEST, but it assumes that the
86 // test will fail with a particular known error condition. Use the DEATH_XXX()
87 // macros from unit_tests.h to specify the expected error condition.
88 #define BPF_DEATH_TEST(test_case_name, test_name, death, policy, aux...) \
89 void BPF_TEST_##test_name( \
90 sandbox::BPFTesterCompatibilityDelegate<aux>::AuxType* BPF_AUX); \
91 TEST(test_case_name, DISABLE_ON_TSAN(test_name)) { \
92 sandbox::SandboxBPFTestRunner bpf_test_runner( \
93 new sandbox::BPFTesterCompatibilityDelegate<aux>(BPF_TEST_##test_name, \
94 policy)); \
95 sandbox::UnitTests::RunTestInProcess(&bpf_test_runner, death); \
96 } \
97 void BPF_TEST_##test_name( \
98 sandbox::BPFTesterCompatibilityDelegate<aux>::AuxType* BPF_AUX)
99
100 // This class takes a simple function pointer as a constructor parameter and a
101 // class name as a template parameter to implement the BPFTesterDelegate
102 // interface which can be used to build BPF unittests with
103 // the SandboxBPFTestRunner class.
104 template <class PolicyClass>
68 class BPFTesterSimpleDelegate : public BPFTesterDelegate { 105 class BPFTesterSimpleDelegate : public BPFTesterDelegate {
69 public: 106 public:
70 typedef Aux AuxType; 107 explicit BPFTesterSimpleDelegate(void (*test_function)(void))
71 BPFTesterSimpleDelegate( 108 : test_function_(test_function) {}
72 void (*test_function)(AuxType*), 109 virtual ~BPFTesterSimpleDelegate() {}
73 typename CompatibilityPolicy<AuxType>::SyscallEvaluator policy_function)
74 : aux_pointer_for_policy_(NULL),
75 test_function_(test_function),
76 policy_function_(policy_function) {
77 // This will be NULL iff AuxType is void.
78 aux_pointer_for_policy_ = NewAux();
79 }
80
81 virtual ~BPFTesterSimpleDelegate() { DeleteAux(aux_pointer_for_policy_); }
82 110
83 virtual scoped_ptr<SandboxBPFPolicy> GetSandboxBPFPolicy() OVERRIDE { 111 virtual scoped_ptr<SandboxBPFPolicy> GetSandboxBPFPolicy() OVERRIDE {
84 // The current method is guaranteed to only run in the child process 112 return scoped_ptr<SandboxBPFPolicy>(new PolicyClass());
85 // running the test. In this process, the current object is guaranteed
86 // to live forever. So it's ok to pass aux_pointer_for_policy_ to
87 // the policy, which could in turn pass it to the kernel via Trap().
88 return scoped_ptr<SandboxBPFPolicy>(new CompatibilityPolicy<AuxType>(
89 policy_function_, aux_pointer_for_policy_));
90 } 113 }
91
92 virtual void RunTestFunction() OVERRIDE { 114 virtual void RunTestFunction() OVERRIDE {
93 // Run the actual test. 115 DCHECK(test_function_);
94 // The current object is guaranteed to live forever in the child process 116 test_function_();
95 // where this will run.
96 test_function_(aux_pointer_for_policy_);
97 } 117 }
98 118
99 private: 119 private:
100 // Allocate an object of type Aux. This is specialized to return NULL when 120 void (*test_function_)(void);
101 // trying to allocate a void.
102 static Aux* NewAux() { return new Aux(); }
103 static void DeleteAux(Aux* aux) { delete aux; }
104
105 AuxType* aux_pointer_for_policy_;
106 void (*test_function_)(AuxType*);
107 typename CompatibilityPolicy<AuxType>::SyscallEvaluator policy_function_;
108 DISALLOW_COPY_AND_ASSIGN(BPFTesterSimpleDelegate); 121 DISALLOW_COPY_AND_ASSIGN(BPFTesterSimpleDelegate);
109 }; 122 };
110 123
111 // Specialization of NewAux that returns NULL;
112 template <>
113 void* BPFTesterSimpleDelegate<void>::NewAux();
114 template <>
115 void BPFTesterSimpleDelegate<void>::DeleteAux(void* aux);
116
117 } // namespace sandbox 124 } // namespace sandbox
118 125
119 #endif // SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTS_H__ 126 #endif // SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTS_H__
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698