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

Side by Side Diff: sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc

Issue 1310773006: Update sandbox/linux from upstream (Closed) Base URL: ssh://ssh.github.com/domokit/mojo.git@master
Patch Set: Update to 3909ebfa69566f7374a6900e63cd4d3c73a35378 Created 5 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 unified diff | Download patch
« no previous file with comments | « sandbox/linux/bpf_dsl/bpf_dsl_impl.h ('k') | sandbox/linux/bpf_dsl/errorcode.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 #include "sandbox/linux/bpf_dsl/bpf_dsl.h" 5 #include "sandbox/linux/bpf_dsl/bpf_dsl.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <netinet/in.h> 9 #include <netinet/in.h>
10 #include <sys/socket.h> 10 #include <sys/socket.h>
11 #include <sys/syscall.h> 11 #include <sys/syscall.h>
12 #include <sys/utsname.h> 12 #include <sys/utsname.h>
13 #include <unistd.h> 13 #include <unistd.h>
14 14
15 #include <map> 15 #include <map>
16 #include <utility> 16 #include <utility>
17 17
18 #include "base/files/scoped_file.h" 18 #include "base/files/scoped_file.h"
19 #include "base/macros.h" 19 #include "base/macros.h"
20 #include "build/build_config.h" 20 #include "build/build_config.h"
21 #include "sandbox/linux/bpf_dsl/bpf_dsl_impl.h" 21 #include "sandbox/linux/bpf_dsl/bpf_dsl_impl.h"
22 #include "sandbox/linux/bpf_dsl/codegen.h" 22 #include "sandbox/linux/bpf_dsl/codegen.h"
23 #include "sandbox/linux/bpf_dsl/policy.h" 23 #include "sandbox/linux/bpf_dsl/policy.h"
24 #include "sandbox/linux/bpf_dsl/policy_compiler.h" 24 #include "sandbox/linux/bpf_dsl/policy_compiler.h"
25 #include "sandbox/linux/bpf_dsl/seccomp_macros.h" 25 #include "sandbox/linux/bpf_dsl/seccomp_macros.h"
26 #include "sandbox/linux/bpf_dsl/trap_registry.h" 26 #include "sandbox/linux/bpf_dsl/test_trap_registry.h"
27 #include "sandbox/linux/bpf_dsl/verifier.h" 27 #include "sandbox/linux/bpf_dsl/verifier.h"
28 #include "sandbox/linux/seccomp-bpf/errorcode.h"
29 #include "sandbox/linux/system_headers/linux_filter.h" 28 #include "sandbox/linux/system_headers/linux_filter.h"
30 #include "testing/gtest/include/gtest/gtest.h" 29 #include "testing/gtest/include/gtest/gtest.h"
31 30
32 #define CASES SANDBOX_BPF_DSL_CASES 31 #define CASES SANDBOX_BPF_DSL_CASES
33 32
34 namespace sandbox { 33 namespace sandbox {
35 namespace bpf_dsl { 34 namespace bpf_dsl {
36 namespace { 35 namespace {
37 36
38 // Helper function to construct fake arch_seccomp_data objects. 37 // Helper function to construct fake arch_seccomp_data objects.
39 struct arch_seccomp_data FakeSyscall(int nr, 38 struct arch_seccomp_data FakeSyscall(int nr,
40 uint64_t p0 = 0, 39 uintptr_t p0 = 0,
41 uint64_t p1 = 0, 40 uintptr_t p1 = 0,
42 uint64_t p2 = 0, 41 uintptr_t p2 = 0,
43 uint64_t p3 = 0, 42 uintptr_t p3 = 0,
44 uint64_t p4 = 0, 43 uintptr_t p4 = 0,
45 uint64_t p5 = 0) { 44 uintptr_t p5 = 0) {
46 // Made up program counter for syscall address. 45 // Made up program counter for syscall address.
47 const uint64_t kFakePC = 0x543210; 46 const uint64_t kFakePC = 0x543210;
48 47
49 struct arch_seccomp_data data = { 48 struct arch_seccomp_data data = {
50 nr, 49 nr,
51 SECCOMP_ARCH, 50 SECCOMP_ARCH,
52 kFakePC, 51 kFakePC,
53 { 52 {
54 p0, p1, p2, p3, p4, p5, 53 p0, p1, p2, p3, p4, p5,
55 }, 54 },
56 }; 55 };
57 56
58 return data; 57 return data;
59 } 58 }
60 59
61 class FakeTrapRegistry : public TrapRegistry {
62 public:
63 FakeTrapRegistry() : map_() {}
64 virtual ~FakeTrapRegistry() {}
65
66 uint16_t Add(TrapFnc fnc, const void* aux, bool safe) override {
67 EXPECT_TRUE(safe);
68
69 const uint16_t next_id = map_.size() + 1;
70 return map_.insert(std::make_pair(Key(fnc, aux), next_id)).first->second;
71 }
72
73 bool EnableUnsafeTraps() override {
74 ADD_FAILURE() << "Unimplemented";
75 return false;
76 }
77
78 private:
79 using Key = std::pair<TrapFnc, const void*>;
80
81 std::map<Key, uint16_t> map_;
82
83 DISALLOW_COPY_AND_ASSIGN(FakeTrapRegistry);
84 };
85
86 intptr_t FakeTrapFuncOne(const arch_seccomp_data& data, void* aux) { return 1; }
87 intptr_t FakeTrapFuncTwo(const arch_seccomp_data& data, void* aux) { return 2; }
88
89 // Test that FakeTrapRegistry correctly assigns trap IDs to trap handlers.
90 TEST(FakeTrapRegistry, TrapIDs) {
91 struct {
92 TrapRegistry::TrapFnc fnc;
93 const void* aux;
94 } funcs[] = {
95 {FakeTrapFuncOne, nullptr},
96 {FakeTrapFuncTwo, nullptr},
97 {FakeTrapFuncOne, funcs},
98 {FakeTrapFuncTwo, funcs},
99 };
100
101 FakeTrapRegistry traps;
102
103 // Add traps twice to test that IDs are reused correctly.
104 for (int i = 0; i < 2; ++i) {
105 for (size_t j = 0; j < arraysize(funcs); ++j) {
106 // Trap IDs start at 1.
107 EXPECT_EQ(j + 1, traps.Add(funcs[j].fnc, funcs[j].aux, true));
108 }
109 }
110 }
111
112 class PolicyEmulator { 60 class PolicyEmulator {
113 public: 61 public:
114 explicit PolicyEmulator(const Policy* policy) : program_(), traps_() { 62 explicit PolicyEmulator(const Policy* policy) : program_(), traps_() {
115 program_ = *PolicyCompiler(policy, &traps_).Compile(true /* verify */); 63 program_ = *PolicyCompiler(policy, &traps_).Compile(true /* verify */);
116 } 64 }
117 ~PolicyEmulator() {} 65 ~PolicyEmulator() {}
118 66
119 uint32_t Emulate(const struct arch_seccomp_data& data) const { 67 uint32_t Emulate(const struct arch_seccomp_data& data) const {
120 const char* err = nullptr; 68 const char* err = nullptr;
121 uint32_t res = Verifier::EvaluateBPF(program_, data, &err); 69 uint32_t res = Verifier::EvaluateBPF(program_, data, &err);
122 if (err) { 70 if (err) {
123 ADD_FAILURE() << err; 71 ADD_FAILURE() << err;
124 return 0; 72 return 0;
125 } 73 }
126 return res; 74 return res;
127 } 75 }
128 76
129 void ExpectAllow(const struct arch_seccomp_data& data) const { 77 void ExpectAllow(const struct arch_seccomp_data& data) const {
130 EXPECT_EQ(SECCOMP_RET_ALLOW, Emulate(data)); 78 EXPECT_EQ(SECCOMP_RET_ALLOW, Emulate(data));
131 } 79 }
132 80
133 void ExpectErrno(uint16_t err, const struct arch_seccomp_data& data) const { 81 void ExpectErrno(uint16_t err, const struct arch_seccomp_data& data) const {
134 EXPECT_EQ(SECCOMP_RET_ERRNO | err, Emulate(data)); 82 EXPECT_EQ(SECCOMP_RET_ERRNO | err, Emulate(data));
135 } 83 }
136 84
85 void ExpectKill(const struct arch_seccomp_data& data) const {
86 EXPECT_EQ(SECCOMP_RET_KILL, Emulate(data));
87 }
88
137 private: 89 private:
138 CodeGen::Program program_; 90 CodeGen::Program program_;
139 FakeTrapRegistry traps_; 91 TestTrapRegistry traps_;
140 92
141 DISALLOW_COPY_AND_ASSIGN(PolicyEmulator); 93 DISALLOW_COPY_AND_ASSIGN(PolicyEmulator);
142 }; 94 };
143 95
144 class BasicPolicy : public Policy { 96 class BasicPolicy : public Policy {
145 public: 97 public:
146 BasicPolicy() {} 98 BasicPolicy() {}
147 ~BasicPolicy() override {} 99 ~BasicPolicy() override {}
148 ResultExpr EvaluateSyscall(int sysno) const override { 100 ResultExpr EvaluateSyscall(int sysno) const override {
149 if (sysno == __NR_getpgid) { 101 if (sysno == __NR_getpgid) {
150 const Arg<pid_t> pid(0); 102 const Arg<pid_t> pid(0);
151 return If(pid == 0, Error(EPERM)).Else(Error(EINVAL)); 103 return If(pid == 0, Error(EPERM)).Else(Error(EINVAL));
152 } 104 }
153 if (sysno == __NR_setuid) { 105 if (sysno == __NR_setuid) {
154 const Arg<uid_t> uid(0); 106 const Arg<uid_t> uid(0);
155 return If(uid != 42, Error(ESRCH)).Else(Error(ENOMEM)); 107 return If(uid != 42, Kill()).Else(Allow());
156 } 108 }
157 return Allow(); 109 return Allow();
158 } 110 }
159 111
160 private: 112 private:
161 DISALLOW_COPY_AND_ASSIGN(BasicPolicy); 113 DISALLOW_COPY_AND_ASSIGN(BasicPolicy);
162 }; 114 };
163 115
164 TEST(BPFDSL, Basic) { 116 TEST(BPFDSL, Basic) {
165 BasicPolicy policy; 117 BasicPolicy policy;
166 PolicyEmulator emulator(&policy); 118 PolicyEmulator emulator(&policy);
167 119
168 emulator.ExpectErrno(EPERM, FakeSyscall(__NR_getpgid, 0)); 120 emulator.ExpectErrno(EPERM, FakeSyscall(__NR_getpgid, 0));
169 emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_getpgid, 1)); 121 emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_getpgid, 1));
170 122
171 emulator.ExpectErrno(ENOMEM, FakeSyscall(__NR_setuid, 42)); 123 emulator.ExpectAllow(FakeSyscall(__NR_setuid, 42));
172 emulator.ExpectErrno(ESRCH, FakeSyscall(__NR_setuid, 43)); 124 emulator.ExpectKill(FakeSyscall(__NR_setuid, 43));
173 } 125 }
174 126
175 /* On IA-32, socketpair() is implemented via socketcall(). :-( */ 127 /* On IA-32, socketpair() is implemented via socketcall(). :-( */
176 #if !defined(ARCH_CPU_X86) 128 #if !defined(ARCH_CPU_X86)
177 class BooleanLogicPolicy : public Policy { 129 class BooleanLogicPolicy : public Policy {
178 public: 130 public:
179 BooleanLogicPolicy() {} 131 BooleanLogicPolicy() {}
180 ~BooleanLogicPolicy() override {} 132 ~BooleanLogicPolicy() override {}
181 ResultExpr EvaluateSyscall(int sysno) const override { 133 ResultExpr EvaluateSyscall(int sysno) const override {
182 if (sysno == __NR_socketpair) { 134 if (sysno == __NR_socketpair) {
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 }; 229 };
278 230
279 TEST(BPFDSL, ArgSizeTest) { 231 TEST(BPFDSL, ArgSizeTest) {
280 ArgSizePolicy policy; 232 ArgSizePolicy policy;
281 PolicyEmulator emulator(&policy); 233 PolicyEmulator emulator(&policy);
282 234
283 emulator.ExpectAllow(FakeSyscall(__NR_uname, 0)); 235 emulator.ExpectAllow(FakeSyscall(__NR_uname, 0));
284 emulator.ExpectErrno(EPERM, FakeSyscall(__NR_uname, kDeadBeefAddr)); 236 emulator.ExpectErrno(EPERM, FakeSyscall(__NR_uname, kDeadBeefAddr));
285 } 237 }
286 238
239 class NegativeConstantsPolicy : public Policy {
240 public:
241 NegativeConstantsPolicy() {}
242 ~NegativeConstantsPolicy() override {}
243 ResultExpr EvaluateSyscall(int sysno) const override {
244 if (sysno == __NR_fcntl) {
245 const Arg<int> fd(0);
246 return If(fd == -314, Error(EPERM)).Else(Allow());
247 }
248 return Allow();
249 }
250
251 private:
252 DISALLOW_COPY_AND_ASSIGN(NegativeConstantsPolicy);
253 };
254
255 TEST(BPFDSL, NegativeConstantsTest) {
256 NegativeConstantsPolicy policy;
257 PolicyEmulator emulator(&policy);
258
259 emulator.ExpectAllow(FakeSyscall(__NR_fcntl, -5, F_DUPFD));
260 emulator.ExpectAllow(FakeSyscall(__NR_fcntl, 20, F_DUPFD));
261 emulator.ExpectErrno(EPERM, FakeSyscall(__NR_fcntl, -314, F_DUPFD));
262 }
263
287 #if 0 264 #if 0
288 // TODO(mdempsky): This is really an integration test. 265 // TODO(mdempsky): This is really an integration test.
289 266
290 class TrappingPolicy : public Policy { 267 class TrappingPolicy : public Policy {
291 public: 268 public:
292 TrappingPolicy() {} 269 TrappingPolicy() {}
293 ~TrappingPolicy() override {} 270 ~TrappingPolicy() override {}
294 ResultExpr EvaluateSyscall(int sysno) const override { 271 ResultExpr EvaluateSyscall(int sysno) const override {
295 if (sysno == __NR_uname) { 272 if (sysno == __NR_uname) {
296 return Trap(UnameTrap, &count_); 273 return Trap(UnameTrap, &count_);
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 EXPECT_TRUE(unsafe->HasUnsafeTraps()); 454 EXPECT_TRUE(unsafe->HasUnsafeTraps());
478 455
479 const Arg<int> arg(0); 456 const Arg<int> arg(0);
480 ResultExpr maybe = If(arg == 0, allow).Else(unsafe); 457 ResultExpr maybe = If(arg == 0, allow).Else(unsafe);
481 EXPECT_TRUE(maybe->HasUnsafeTraps()); 458 EXPECT_TRUE(maybe->HasUnsafeTraps());
482 } 459 }
483 460
484 } // namespace 461 } // namespace
485 } // namespace bpf_dsl 462 } // namespace bpf_dsl
486 } // namespace sandbox 463 } // namespace sandbox
OLDNEW
« no previous file with comments | « sandbox/linux/bpf_dsl/bpf_dsl_impl.h ('k') | sandbox/linux/bpf_dsl/errorcode.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698