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

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: 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 // A BPF_DEATH_TEST is just the same as a BPF_TEST, but it assumes that the
24 // test will fail with a particular known error condition. Use the DEATH_XXX() 16 // test will fail with a particular known error condition. Use the DEATH_XXX()
25 // macros from unit_tests.h to specify the expected error condition. 17 // macros from unit_tests.h to specify the expected error condition.
26 // A BPF_DEATH_TEST is always disabled under ThreadSanitizer, see 18 // A BPF_DEATH_TEST is always disabled under ThreadSanitizer, see
27 // crbug.com/243968. 19 // crbug.com/243968.
28 #define BPF_DEATH_TEST(test_case_name, test_name, death, policy, aux...) \ 20 #define BPF_DEATH_TEST(test_case_name, test_name, death, policy, aux...) \
29 void BPF_TEST_##test_name( \ 21 void BPF_TEST_##test_name( \
30 sandbox::BPFTesterSimpleDelegate<aux>::AuxType* BPF_AUX); \ 22 sandbox::BPFTesterCompatibilityDelegate<aux>::AuxType* BPF_AUX); \
31 TEST(test_case_name, DISABLE_ON_TSAN(test_name)) { \ 23 TEST(test_case_name, DISABLE_ON_TSAN(test_name)) { \
32 sandbox::SandboxBPFTestRunner bpf_test_runner( \ 24 sandbox::SandboxBPFTestRunner bpf_test_runner( \
33 new sandbox::BPFTesterSimpleDelegate<aux>(BPF_TEST_##test_name, \ 25 new sandbox::BPFTesterCompatibilityDelegate<aux>(BPF_TEST_##test_name, \
34 policy)); \ 26 policy)); \
35 sandbox::UnitTests::RunTestInProcess(&bpf_test_runner, death); \ 27 sandbox::UnitTests::RunTestInProcess(&bpf_test_runner, death); \
36 } \ 28 } \
37 void BPF_TEST_##test_name( \ 29 void BPF_TEST_##test_name( \
38 sandbox::BPFTesterSimpleDelegate<aux>::AuxType* BPF_AUX) 30 sandbox::BPFTesterCompatibilityDelegate<aux>::AuxType* BPF_AUX)
39 31
40 // BPF_TEST() is a special version of SANDBOX_TEST(). It turns into a no-op, 32 // This form of BPF_TEST is now discouraged (but still allowed) in favor of
mdempsky 2014/05/07 00:57:39 Doesn't need to be addressed in this CL, but the o
jln (very slow on Chromium) 2014/05/07 01:07:37 Done, thanks!
41 // if the host does not have kernel support for running BPF filters. 33 // BPF_TEST_D and BPF_TEST_C.
42 // Also, it takes advantage of the Die class to avoid calling LOG(FATAL), from 34 // BPF_TEST() is a special version of SANDBOX_TEST(). It runs a test function
43 // inside our tests, as we don't need or even want all the error handling that 35 // in a sub-process, under a seccomp-bpf policy specified in |policy| without
44 // LOG(FATAL) would do. 36 // failing on configurations that are allowed to not support seccomp-bpf in
37 // their kernels.
38 // The |policy| parameter should be a SyscallEvaluator function pointer
39 // (which is now a deprecated way of expressing policies).
45 // BPF_TEST() takes a C++ data type as an optional fourth parameter. If 40 // BPF_TEST() takes a C++ data type as an optional fourth parameter. If
46 // present, this sets up a variable that can be accessed as "BPF_AUX". This 41 // present, this sets up a variable that can be accessed as "BPF_AUX". This
47 // variable will be passed as an argument to the "policy" function. Policies 42 // variable will be passed as an argument to the "policy" function. Policies
48 // would typically use it as an argument to SandboxBPF::Trap(), if they want to 43 // would typically use it as an argument to SandboxBPF::Trap(), if they want to
49 // communicate data between the BPF_TEST() and a Trap() function. The life-time 44 // communicate data between the BPF_TEST() and a Trap() function. The life-time
50 // of this object is the same as the life-time of the process. 45 // of this object is the same as the life-time of the process running under the
46 // seccomp-bpf policy.
51 // The type specified in |aux| and the last parameter of the policy function 47 // The type specified in |aux| and the last parameter of the policy function
52 // must be compatible. If |aux| is not specified, the policy function must 48 // must be compatible. If |aux| is not specified, the policy function must
53 // take a void* as its last parameter (that is, must have the EvaluateSyscall 49 // take a void* as its last parameter (that is, must have the EvaluateSyscall
54 // type). 50 // type).
55 #define BPF_TEST(test_case_name, test_name, policy, aux...) \ 51 #define BPF_TEST(test_case_name, test_name, policy, aux...) \
56 BPF_DEATH_TEST(test_case_name, test_name, DEATH_SUCCESS(), policy, aux) 52 BPF_DEATH_TEST(test_case_name, test_name, DEATH_SUCCESS(), policy, aux)
57 53
54 #define BPF_DEATH_TEST_D( \
55 test_case_name, test_name, death, bpf_tester_delegate_class) \
56 TEST(test_case_name, DISABLE_ON_TSAN(test_name)) { \
57 sandbox::SandboxBPFTestRunner bpf_test_runner( \
58 new bpf_tester_delegate_class()); \
59 sandbox::UnitTests::RunTestInProcess(&bpf_test_runner, death); \
60 }
61
62 // This form of BPF_TEST is a little verbose and should be reserved for complex
63 // tests where a lot of control is required.
64 // |bpf_tester_delegate_class| must be a classname implementing the
65 // BPFTesterDelegate interface.
66 #define BPF_TEST_D(test_case_name, test_name, bpf_tester_delegate_class) \
67 BPF_DEATH_TEST_D( \
68 test_case_name, test_name, DEATH_SUCCESS(), bpf_tester_delegate_class)
69
70 // This class takes a simple function pointer as a constructor parameter and a
71 // class name as a template parameter to implement the BPFTesterDelegate
72 // interface which can be used to build BPF unittests with
73 // the SandboxBPFTestRunner class.
74 template <class PolicyClass>
75 class BPFTesterSimpleDelegate : public BPFTesterDelegate {
76 public:
77 explicit BPFTesterSimpleDelegate(void (*test_function)(void))
78 : test_function_(test_function) {}
79 virtual ~BPFTesterSimpleDelegate() {}
80
81 virtual scoped_ptr<SandboxBPFPolicy> GetSandboxBPFPolicy() OVERRIDE {
82 return scoped_ptr<SandboxBPFPolicy>(new PolicyClass());
83 }
84 virtual void RunTestFunction() OVERRIDE {
85 DCHECK(test_function_);
86 test_function_();
87 }
88
89 private:
90 void (*test_function_)(void);
91 DISALLOW_COPY_AND_ASSIGN(BPFTesterSimpleDelegate);
92 };
93
94 #define BPF_DEATH_TEST_C( \
95 test_case_name, test_name, death, bpf_policy_class_name) \
96 void BPF_TEST_C_##test_name(); \
97 TEST(test_case_name, DISABLE_ON_TSAN(test_name)) { \
98 sandbox::SandboxBPFTestRunner bpf_test_runner( \
99 new BPFTesterSimpleDelegate<bpf_policy_class_name>( \
100 BPF_TEST_C_##test_name)); \
101 sandbox::UnitTests::RunTestInProcess(&bpf_test_runner, death); \
102 } \
103 void BPF_TEST_C_##test_name()
104
105 // This is the prefered format for new BPF tests. It takes a class name
mdempsky 2014/05/07 00:57:39 Nit: Preferred has two 'r's.
jln (very slow on Chromium) 2014/05/07 01:07:37 Done.
106 // that implements the policy (which will be default-constructed) and
107 // the test function's body can simply follow.
108 #define BPF_TEST_C(test_case_name, test_name, bpf_policy_class_name) \
109 BPF_DEATH_TEST_C( \
110 test_case_name, test_name, DEATH_SUCCESS(), bpf_policy_class_name)
111
58 // Assertions are handled exactly the same as with a normal SANDBOX_TEST() 112 // Assertions are handled exactly the same as with a normal SANDBOX_TEST()
59 #define BPF_ASSERT SANDBOX_ASSERT 113 #define BPF_ASSERT SANDBOX_ASSERT
60 #define BPF_ASSERT_EQ(x, y) BPF_ASSERT((x) == (y)) 114 #define BPF_ASSERT_EQ(x, y) BPF_ASSERT((x) == (y))
61 #define BPF_ASSERT_NE(x, y) BPF_ASSERT((x) != (y)) 115 #define BPF_ASSERT_NE(x, y) BPF_ASSERT((x) != (y))
62 #define BPF_ASSERT_LT(x, y) BPF_ASSERT((x) < (y)) 116 #define BPF_ASSERT_LT(x, y) BPF_ASSERT((x) < (y))
63 #define BPF_ASSERT_GT(x, y) BPF_ASSERT((x) > (y)) 117 #define BPF_ASSERT_GT(x, y) BPF_ASSERT((x) > (y))
64 #define BPF_ASSERT_LE(x, y) BPF_ASSERT((x) <= (y)) 118 #define BPF_ASSERT_LE(x, y) BPF_ASSERT((x) <= (y))
65 #define BPF_ASSERT_GE(x, y) BPF_ASSERT((x) >= (y)) 119 #define BPF_ASSERT_GE(x, y) BPF_ASSERT((x) >= (y))
66 120
67 template <class Aux = void>
68 class BPFTesterSimpleDelegate : public BPFTesterDelegate {
69 public:
70 typedef Aux AuxType;
71 BPFTesterSimpleDelegate(
72 void (*test_function)(AuxType*),
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
83 virtual scoped_ptr<SandboxBPFPolicy> GetSandboxBPFPolicy() OVERRIDE {
84 // The current method is guaranteed to only run in the child process
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 }
91
92 virtual void RunTestFunction() OVERRIDE {
93 // Run the actual test.
94 // The current object is guaranteed to live forever in the child process
95 // where this will run.
96 test_function_(aux_pointer_for_policy_);
97 }
98
99 private:
100 // Allocate an object of type Aux. This is specialized to return NULL when
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);
109 };
110
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 121 } // namespace sandbox
118 122
119 #endif // SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTS_H__ 123 #endif // SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTS_H__
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698