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

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

Issue 1001833005: Update from https://crrev.com/320343 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Supress Created 5 years, 9 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/BUILD.gn ('k') | sandbox/linux/bpf_dsl/policy_compiler.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>
16 #include <utility>
17
15 #include "base/files/scoped_file.h" 18 #include "base/files/scoped_file.h"
16 #include "base/macros.h" 19 #include "base/macros.h"
17 #include "build/build_config.h" 20 #include "build/build_config.h"
18 #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"
19 #include "sandbox/linux/bpf_dsl/policy.h" 23 #include "sandbox/linux/bpf_dsl/policy.h"
20 #include "sandbox/linux/seccomp-bpf/bpf_tests.h" 24 #include "sandbox/linux/bpf_dsl/policy_compiler.h"
25 #include "sandbox/linux/bpf_dsl/seccomp_macros.h"
26 #include "sandbox/linux/bpf_dsl/trap_registry.h"
27 #include "sandbox/linux/bpf_dsl/verifier.h"
21 #include "sandbox/linux/seccomp-bpf/errorcode.h" 28 #include "sandbox/linux/seccomp-bpf/errorcode.h"
22 #include "sandbox/linux/seccomp-bpf/syscall.h"
23 #include "testing/gtest/include/gtest/gtest.h" 29 #include "testing/gtest/include/gtest/gtest.h"
24 30
25 #define CASES SANDBOX_BPF_DSL_CASES 31 #define CASES SANDBOX_BPF_DSL_CASES
26 32
27 // Helper macro to assert that invoking system call |sys| directly via
28 // Syscall::Call with arguments |...| returns |res|.
29 // Errors can be asserted by specifying a value like "-EINVAL".
30 #define ASSERT_SYSCALL_RESULT(res, sys, ...) \
31 BPF_ASSERT_EQ(res, Stubs::sys(__VA_ARGS__))
32
33 namespace sandbox { 33 namespace sandbox {
34 namespace bpf_dsl { 34 namespace bpf_dsl {
35 namespace { 35 namespace {
36 36
37 // Type safe stubs for tested system calls. 37 // Helper function to construct fake arch_seccomp_data objects.
38 class Stubs { 38 struct arch_seccomp_data FakeSyscall(int nr,
39 uint64_t p0 = 0,
40 uint64_t p1 = 0,
41 uint64_t p2 = 0,
42 uint64_t p3 = 0,
43 uint64_t p4 = 0,
44 uint64_t p5 = 0) {
45 // Made up program counter for syscall address.
46 const uint64_t kFakePC = 0x543210;
47
48 struct arch_seccomp_data data = {
49 nr,
50 SECCOMP_ARCH,
51 kFakePC,
52 {
53 p0, p1, p2, p3, p4, p5,
54 },
55 };
56
57 return data;
58 }
59
60 class FakeTrapRegistry : public TrapRegistry {
39 public: 61 public:
40 static int getpgid(pid_t pid) { return Syscall::Call(__NR_getpgid, pid); } 62 FakeTrapRegistry() : map_() {}
41 static int setuid(uid_t uid) { return Syscall::Call(__NR_setuid, uid); } 63 virtual ~FakeTrapRegistry() {}
42 static int setgid(gid_t gid) { return Syscall::Call(__NR_setgid, gid); } 64
43 static int setpgid(pid_t pid, pid_t pgid) { 65 uint16_t Add(TrapFnc fnc, const void* aux, bool safe) override {
44 return Syscall::Call(__NR_setpgid, pid, pgid); 66 EXPECT_TRUE(safe);
67
68 const uint16_t next_id = map_.size() + 1;
69 return map_.insert(std::make_pair(Key(fnc, aux), next_id)).first->second;
45 } 70 }
46 71
47 static int fcntl(int fd, int cmd, unsigned long arg = 0) { 72 bool EnableUnsafeTraps() override {
48 return Syscall::Call(__NR_fcntl, fd, cmd, arg); 73 ADD_FAILURE() << "Unimplemented";
74 return false;
49 } 75 }
50 76
51 static int uname(struct utsname* buf) { 77 private:
52 return Syscall::Call(__NR_uname, buf); 78 using Key = std::pair<TrapFnc, const void*>;
79
80 std::map<Key, uint16_t> map_;
81
82 DISALLOW_COPY_AND_ASSIGN(FakeTrapRegistry);
83 };
84
85 intptr_t FakeTrapFuncOne(const arch_seccomp_data& data, void* aux) { return 1; }
86 intptr_t FakeTrapFuncTwo(const arch_seccomp_data& data, void* aux) { return 2; }
87
88 // Test that FakeTrapRegistry correctly assigns trap IDs to trap handlers.
89 TEST(FakeTrapRegistry, TrapIDs) {
90 struct {
91 TrapRegistry::TrapFnc fnc;
92 const void* aux;
93 } funcs[] = {
94 {FakeTrapFuncOne, nullptr},
95 {FakeTrapFuncTwo, nullptr},
96 {FakeTrapFuncOne, funcs},
97 {FakeTrapFuncTwo, funcs},
98 };
99
100 FakeTrapRegistry traps;
101
102 // Add traps twice to test that IDs are reused correctly.
103 for (int i = 0; i < 2; ++i) {
104 for (size_t j = 0; j < arraysize(funcs); ++j) {
105 // Trap IDs start at 1.
106 EXPECT_EQ(j + 1, traps.Add(funcs[j].fnc, funcs[j].aux, true));
107 }
108 }
109 }
110
111 class PolicyEmulator {
112 public:
113 explicit PolicyEmulator(const Policy* policy) : program_(), traps_() {
114 program_ = *PolicyCompiler(policy, &traps_).Compile(true /* verify */);
115 }
116 ~PolicyEmulator() {}
117
118 uint32_t Emulate(const struct arch_seccomp_data& data) const {
119 const char* err = nullptr;
120 uint32_t res = Verifier::EvaluateBPF(program_, data, &err);
121 if (err) {
122 ADD_FAILURE() << err;
123 return 0;
124 }
125 return res;
53 } 126 }
54 127
55 static int setresuid(uid_t ruid, uid_t euid, uid_t suid) { 128 void ExpectAllow(const struct arch_seccomp_data& data) const {
56 return Syscall::Call(__NR_setresuid, ruid, euid, suid); 129 EXPECT_EQ(SECCOMP_RET_ALLOW, Emulate(data));
57 } 130 }
58 131
59 #if !defined(ARCH_CPU_X86) 132 void ExpectErrno(uint16_t err, const struct arch_seccomp_data& data) const {
60 static int socketpair(int domain, int type, int protocol, int sv[2]) { 133 EXPECT_EQ(SECCOMP_RET_ERRNO | err, Emulate(data));
61 return Syscall::Call(__NR_socketpair, domain, type, protocol, sv);
62 } 134 }
63 #endif 135
136 private:
137 CodeGen::Program program_;
138 FakeTrapRegistry traps_;
139
140 DISALLOW_COPY_AND_ASSIGN(PolicyEmulator);
64 }; 141 };
65 142
66 class BasicPolicy : public Policy { 143 class BasicPolicy : public Policy {
67 public: 144 public:
68 BasicPolicy() {} 145 BasicPolicy() {}
69 ~BasicPolicy() override {} 146 ~BasicPolicy() override {}
70 ResultExpr EvaluateSyscall(int sysno) const override { 147 ResultExpr EvaluateSyscall(int sysno) const override {
71 if (sysno == __NR_getpgid) { 148 if (sysno == __NR_getpgid) {
72 const Arg<pid_t> pid(0); 149 const Arg<pid_t> pid(0);
73 return If(pid == 0, Error(EPERM)).Else(Error(EINVAL)); 150 return If(pid == 0, Error(EPERM)).Else(Error(EINVAL));
74 } 151 }
75 if (sysno == __NR_setuid) { 152 if (sysno == __NR_setuid) {
76 const Arg<uid_t> uid(0); 153 const Arg<uid_t> uid(0);
77 return If(uid != 42, Error(ESRCH)).Else(Error(ENOMEM)); 154 return If(uid != 42, Error(ESRCH)).Else(Error(ENOMEM));
78 } 155 }
79 return Allow(); 156 return Allow();
80 } 157 }
81 158
82 private: 159 private:
83 DISALLOW_COPY_AND_ASSIGN(BasicPolicy); 160 DISALLOW_COPY_AND_ASSIGN(BasicPolicy);
84 }; 161 };
85 162
86 BPF_TEST_C(BPFDSL, Basic, BasicPolicy) { 163 TEST(BPFDSL, Basic) {
87 ASSERT_SYSCALL_RESULT(-EPERM, getpgid, 0); 164 BasicPolicy policy;
88 ASSERT_SYSCALL_RESULT(-EINVAL, getpgid, 1); 165 PolicyEmulator emulator(&policy);
89 166
90 ASSERT_SYSCALL_RESULT(-ENOMEM, setuid, 42); 167 emulator.ExpectErrno(EPERM, FakeSyscall(__NR_getpgid, 0));
91 ASSERT_SYSCALL_RESULT(-ESRCH, setuid, 43); 168 emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_getpgid, 1));
169
170 emulator.ExpectErrno(ENOMEM, FakeSyscall(__NR_setuid, 42));
171 emulator.ExpectErrno(ESRCH, FakeSyscall(__NR_setuid, 43));
92 } 172 }
93 173
94 /* On IA-32, socketpair() is implemented via socketcall(). :-( */ 174 /* On IA-32, socketpair() is implemented via socketcall(). :-( */
95 #if !defined(ARCH_CPU_X86) 175 #if !defined(ARCH_CPU_X86)
96 class BooleanLogicPolicy : public Policy { 176 class BooleanLogicPolicy : public Policy {
97 public: 177 public:
98 BooleanLogicPolicy() {} 178 BooleanLogicPolicy() {}
99 ~BooleanLogicPolicy() override {} 179 ~BooleanLogicPolicy() override {}
100 ResultExpr EvaluateSyscall(int sysno) const override { 180 ResultExpr EvaluateSyscall(int sysno) const override {
101 if (sysno == __NR_socketpair) { 181 if (sysno == __NR_socketpair) {
102 const Arg<int> domain(0), type(1), protocol(2); 182 const Arg<int> domain(0), type(1), protocol(2);
103 return If(domain == AF_UNIX && 183 return If(domain == AF_UNIX &&
104 (type == SOCK_STREAM || type == SOCK_DGRAM) && 184 (type == SOCK_STREAM || type == SOCK_DGRAM) &&
105 protocol == 0, 185 protocol == 0,
106 Error(EPERM)).Else(Error(EINVAL)); 186 Error(EPERM)).Else(Error(EINVAL));
107 } 187 }
108 return Allow(); 188 return Allow();
109 } 189 }
110 190
111 private: 191 private:
112 DISALLOW_COPY_AND_ASSIGN(BooleanLogicPolicy); 192 DISALLOW_COPY_AND_ASSIGN(BooleanLogicPolicy);
113 }; 193 };
114 194
115 BPF_TEST_C(BPFDSL, BooleanLogic, BooleanLogicPolicy) { 195 TEST(BPFDSL, BooleanLogic) {
116 int sv[2]; 196 BooleanLogicPolicy policy;
197 PolicyEmulator emulator(&policy);
198
199 const intptr_t kFakeSV = 0x12345;
117 200
118 // Acceptable combinations that should return EPERM. 201 // Acceptable combinations that should return EPERM.
119 ASSERT_SYSCALL_RESULT(-EPERM, socketpair, AF_UNIX, SOCK_STREAM, 0, sv); 202 emulator.ExpectErrno(
120 ASSERT_SYSCALL_RESULT(-EPERM, socketpair, AF_UNIX, SOCK_DGRAM, 0, sv); 203 EPERM, FakeSyscall(__NR_socketpair, AF_UNIX, SOCK_STREAM, 0, kFakeSV));
204 emulator.ExpectErrno(
205 EPERM, FakeSyscall(__NR_socketpair, AF_UNIX, SOCK_DGRAM, 0, kFakeSV));
121 206
122 // Combinations that are invalid for only one reason; should return EINVAL. 207 // Combinations that are invalid for only one reason; should return EINVAL.
123 ASSERT_SYSCALL_RESULT(-EINVAL, socketpair, AF_INET, SOCK_STREAM, 0, sv); 208 emulator.ExpectErrno(
124 ASSERT_SYSCALL_RESULT(-EINVAL, socketpair, AF_UNIX, SOCK_SEQPACKET, 0, sv); 209 EINVAL, FakeSyscall(__NR_socketpair, AF_INET, SOCK_STREAM, 0, kFakeSV));
125 ASSERT_SYSCALL_RESULT( 210 emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_socketpair, AF_UNIX,
126 -EINVAL, socketpair, AF_UNIX, SOCK_STREAM, IPPROTO_TCP, sv); 211 SOCK_SEQPACKET, 0, kFakeSV));
212 emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_socketpair, AF_UNIX,
213 SOCK_STREAM, IPPROTO_TCP, kFakeSV));
127 214
128 // Completely unacceptable combination; should also return EINVAL. 215 // Completely unacceptable combination; should also return EINVAL.
129 ASSERT_SYSCALL_RESULT( 216 emulator.ExpectErrno(
130 -EINVAL, socketpair, AF_INET, SOCK_SEQPACKET, IPPROTO_UDP, sv); 217 EINVAL, FakeSyscall(__NR_socketpair, AF_INET, SOCK_SEQPACKET, IPPROTO_UDP,
218 kFakeSV));
131 } 219 }
132 #endif // !ARCH_CPU_X86 220 #endif // !ARCH_CPU_X86
133 221
134 class MoreBooleanLogicPolicy : public Policy { 222 class MoreBooleanLogicPolicy : public Policy {
135 public: 223 public:
136 MoreBooleanLogicPolicy() {} 224 MoreBooleanLogicPolicy() {}
137 ~MoreBooleanLogicPolicy() override {} 225 ~MoreBooleanLogicPolicy() override {}
138 ResultExpr EvaluateSyscall(int sysno) const override { 226 ResultExpr EvaluateSyscall(int sysno) const override {
139 if (sysno == __NR_setresuid) { 227 if (sysno == __NR_setresuid) {
140 const Arg<uid_t> ruid(0), euid(1), suid(2); 228 const Arg<uid_t> ruid(0), euid(1), suid(2);
141 return If(ruid == 0 || euid == 0 || suid == 0, Error(EPERM)) 229 return If(ruid == 0 || euid == 0 || suid == 0, Error(EPERM))
142 .ElseIf(ruid == 1 && euid == 1 && suid == 1, Error(EAGAIN)) 230 .ElseIf(ruid == 1 && euid == 1 && suid == 1, Error(EAGAIN))
143 .Else(Error(EINVAL)); 231 .Else(Error(EINVAL));
144 } 232 }
145 return Allow(); 233 return Allow();
146 } 234 }
147 235
148 private: 236 private:
149 DISALLOW_COPY_AND_ASSIGN(MoreBooleanLogicPolicy); 237 DISALLOW_COPY_AND_ASSIGN(MoreBooleanLogicPolicy);
150 }; 238 };
151 239
152 BPF_TEST_C(BPFDSL, MoreBooleanLogic, MoreBooleanLogicPolicy) { 240 TEST(BPFDSL, MoreBooleanLogic) {
241 MoreBooleanLogicPolicy policy;
242 PolicyEmulator emulator(&policy);
243
153 // Expect EPERM if any set to 0. 244 // Expect EPERM if any set to 0.
154 ASSERT_SYSCALL_RESULT(-EPERM, setresuid, 0, 5, 5); 245 emulator.ExpectErrno(EPERM, FakeSyscall(__NR_setresuid, 0, 5, 5));
155 ASSERT_SYSCALL_RESULT(-EPERM, setresuid, 5, 0, 5); 246 emulator.ExpectErrno(EPERM, FakeSyscall(__NR_setresuid, 5, 0, 5));
156 ASSERT_SYSCALL_RESULT(-EPERM, setresuid, 5, 5, 0); 247 emulator.ExpectErrno(EPERM, FakeSyscall(__NR_setresuid, 5, 5, 0));
157 248
158 // Expect EAGAIN if all set to 1. 249 // Expect EAGAIN if all set to 1.
159 ASSERT_SYSCALL_RESULT(-EAGAIN, setresuid, 1, 1, 1); 250 emulator.ExpectErrno(EAGAIN, FakeSyscall(__NR_setresuid, 1, 1, 1));
160 251
161 // Expect EINVAL for anything else. 252 // Expect EINVAL for anything else.
162 ASSERT_SYSCALL_RESULT(-EINVAL, setresuid, 5, 1, 1); 253 emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_setresuid, 5, 1, 1));
163 ASSERT_SYSCALL_RESULT(-EINVAL, setresuid, 1, 5, 1); 254 emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_setresuid, 1, 5, 1));
164 ASSERT_SYSCALL_RESULT(-EINVAL, setresuid, 1, 1, 5); 255 emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_setresuid, 1, 1, 5));
165 ASSERT_SYSCALL_RESULT(-EINVAL, setresuid, 3, 4, 5); 256 emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_setresuid, 3, 4, 5));
166 } 257 }
167 258
168 static const uintptr_t kDeadBeefAddr = 259 static const uintptr_t kDeadBeefAddr =
169 static_cast<uintptr_t>(0xdeadbeefdeadbeefULL); 260 static_cast<uintptr_t>(0xdeadbeefdeadbeefULL);
170 261
171 class ArgSizePolicy : public Policy { 262 class ArgSizePolicy : public Policy {
172 public: 263 public:
173 ArgSizePolicy() {} 264 ArgSizePolicy() {}
174 ~ArgSizePolicy() override {} 265 ~ArgSizePolicy() override {}
175 ResultExpr EvaluateSyscall(int sysno) const override { 266 ResultExpr EvaluateSyscall(int sysno) const override {
176 if (sysno == __NR_uname) { 267 if (sysno == __NR_uname) {
177 const Arg<uintptr_t> addr(0); 268 const Arg<uintptr_t> addr(0);
178 return If(addr == kDeadBeefAddr, Error(EPERM)).Else(Allow()); 269 return If(addr == kDeadBeefAddr, Error(EPERM)).Else(Allow());
179 } 270 }
180 return Allow(); 271 return Allow();
181 } 272 }
182 273
183 private: 274 private:
184 DISALLOW_COPY_AND_ASSIGN(ArgSizePolicy); 275 DISALLOW_COPY_AND_ASSIGN(ArgSizePolicy);
185 }; 276 };
186 277
187 BPF_TEST_C(BPFDSL, ArgSizeTest, ArgSizePolicy) { 278 TEST(BPFDSL, ArgSizeTest) {
188 struct utsname buf; 279 ArgSizePolicy policy;
189 ASSERT_SYSCALL_RESULT(0, uname, &buf); 280 PolicyEmulator emulator(&policy);
190 ASSERT_SYSCALL_RESULT( 281
191 -EPERM, uname, reinterpret_cast<struct utsname*>(kDeadBeefAddr)); 282 emulator.ExpectAllow(FakeSyscall(__NR_uname, 0));
283 emulator.ExpectErrno(EPERM, FakeSyscall(__NR_uname, kDeadBeefAddr));
192 } 284 }
193 285
286 #if 0
287 // TODO(mdempsky): This is really an integration test.
288
194 class TrappingPolicy : public Policy { 289 class TrappingPolicy : public Policy {
195 public: 290 public:
196 TrappingPolicy() {} 291 TrappingPolicy() {}
197 ~TrappingPolicy() override {} 292 ~TrappingPolicy() override {}
198 ResultExpr EvaluateSyscall(int sysno) const override { 293 ResultExpr EvaluateSyscall(int sysno) const override {
199 if (sysno == __NR_uname) { 294 if (sysno == __NR_uname) {
200 return Trap(UnameTrap, &count_); 295 return Trap(UnameTrap, &count_);
201 } 296 }
202 return Allow(); 297 return Allow();
203 } 298 }
204 299
205 private: 300 private:
206 static intptr_t count_; 301 static intptr_t count_;
207 302
208 static intptr_t UnameTrap(const struct arch_seccomp_data& data, void* aux) { 303 static intptr_t UnameTrap(const struct arch_seccomp_data& data, void* aux) {
209 BPF_ASSERT_EQ(&count_, aux); 304 BPF_ASSERT_EQ(&count_, aux);
210 return ++count_; 305 return ++count_;
211 } 306 }
212 307
213 DISALLOW_COPY_AND_ASSIGN(TrappingPolicy); 308 DISALLOW_COPY_AND_ASSIGN(TrappingPolicy);
214 }; 309 };
215 310
216 intptr_t TrappingPolicy::count_; 311 intptr_t TrappingPolicy::count_;
217 312
218 BPF_TEST_C(BPFDSL, TrapTest, TrappingPolicy) { 313 BPF_TEST_C(BPFDSL, TrapTest, TrappingPolicy) {
219 ASSERT_SYSCALL_RESULT(1, uname, NULL); 314 ASSERT_SYSCALL_RESULT(1, uname, NULL);
220 ASSERT_SYSCALL_RESULT(2, uname, NULL); 315 ASSERT_SYSCALL_RESULT(2, uname, NULL);
221 ASSERT_SYSCALL_RESULT(3, uname, NULL); 316 ASSERT_SYSCALL_RESULT(3, uname, NULL);
222 } 317 }
318 #endif
223 319
224 class MaskingPolicy : public Policy { 320 class MaskingPolicy : public Policy {
225 public: 321 public:
226 MaskingPolicy() {} 322 MaskingPolicy() {}
227 ~MaskingPolicy() override {} 323 ~MaskingPolicy() override {}
228 ResultExpr EvaluateSyscall(int sysno) const override { 324 ResultExpr EvaluateSyscall(int sysno) const override {
229 if (sysno == __NR_setuid) { 325 if (sysno == __NR_setuid) {
230 const Arg<uid_t> uid(0); 326 const Arg<uid_t> uid(0);
231 return If((uid & 0xf) == 0, Error(EINVAL)).Else(Error(EACCES)); 327 return If((uid & 0xf) == 0, Error(EINVAL)).Else(Error(EACCES));
232 } 328 }
233 if (sysno == __NR_setgid) { 329 if (sysno == __NR_setgid) {
234 const Arg<gid_t> gid(0); 330 const Arg<gid_t> gid(0);
235 return If((gid & 0xf0) == 0xf0, Error(EINVAL)).Else(Error(EACCES)); 331 return If((gid & 0xf0) == 0xf0, Error(EINVAL)).Else(Error(EACCES));
236 } 332 }
237 if (sysno == __NR_setpgid) { 333 if (sysno == __NR_setpgid) {
238 const Arg<pid_t> pid(0); 334 const Arg<pid_t> pid(0);
239 return If((pid & 0xa5) == 0xa0, Error(EINVAL)).Else(Error(EACCES)); 335 return If((pid & 0xa5) == 0xa0, Error(EINVAL)).Else(Error(EACCES));
240 } 336 }
241 return Allow(); 337 return Allow();
242 } 338 }
243 339
244 private: 340 private:
245 DISALLOW_COPY_AND_ASSIGN(MaskingPolicy); 341 DISALLOW_COPY_AND_ASSIGN(MaskingPolicy);
246 }; 342 };
247 343
248 BPF_TEST_C(BPFDSL, MaskTest, MaskingPolicy) { 344 TEST(BPFDSL, MaskTest) {
345 MaskingPolicy policy;
346 PolicyEmulator emulator(&policy);
347
249 for (uid_t uid = 0; uid < 0x100; ++uid) { 348 for (uid_t uid = 0; uid < 0x100; ++uid) {
250 const int expect_errno = (uid & 0xf) == 0 ? EINVAL : EACCES; 349 const int expect_errno = (uid & 0xf) == 0 ? EINVAL : EACCES;
251 ASSERT_SYSCALL_RESULT(-expect_errno, setuid, uid); 350 emulator.ExpectErrno(expect_errno, FakeSyscall(__NR_setuid, uid));
252 } 351 }
253 352
254 for (gid_t gid = 0; gid < 0x100; ++gid) { 353 for (gid_t gid = 0; gid < 0x100; ++gid) {
255 const int expect_errno = (gid & 0xf0) == 0xf0 ? EINVAL : EACCES; 354 const int expect_errno = (gid & 0xf0) == 0xf0 ? EINVAL : EACCES;
256 ASSERT_SYSCALL_RESULT(-expect_errno, setgid, gid); 355 emulator.ExpectErrno(expect_errno, FakeSyscall(__NR_setgid, gid));
257 } 356 }
258 357
259 for (pid_t pid = 0; pid < 0x100; ++pid) { 358 for (pid_t pid = 0; pid < 0x100; ++pid) {
260 const int expect_errno = (pid & 0xa5) == 0xa0 ? EINVAL : EACCES; 359 const int expect_errno = (pid & 0xa5) == 0xa0 ? EINVAL : EACCES;
261 ASSERT_SYSCALL_RESULT(-expect_errno, setpgid, pid, 0); 360 emulator.ExpectErrno(expect_errno, FakeSyscall(__NR_setpgid, pid, 0));
262 } 361 }
263 } 362 }
264 363
265 class ElseIfPolicy : public Policy { 364 class ElseIfPolicy : public Policy {
266 public: 365 public:
267 ElseIfPolicy() {} 366 ElseIfPolicy() {}
268 ~ElseIfPolicy() override {} 367 ~ElseIfPolicy() override {}
269 ResultExpr EvaluateSyscall(int sysno) const override { 368 ResultExpr EvaluateSyscall(int sysno) const override {
270 if (sysno == __NR_setuid) { 369 if (sysno == __NR_setuid) {
271 const Arg<uid_t> uid(0); 370 const Arg<uid_t> uid(0);
272 return If((uid & 0xfff) == 0, Error(0)) 371 return If((uid & 0xfff) == 0, Error(0))
273 .ElseIf((uid & 0xff0) == 0, Error(EINVAL)) 372 .ElseIf((uid & 0xff0) == 0, Error(EINVAL))
274 .ElseIf((uid & 0xf00) == 0, Error(EEXIST)) 373 .ElseIf((uid & 0xf00) == 0, Error(EEXIST))
275 .Else(Error(EACCES)); 374 .Else(Error(EACCES));
276 } 375 }
277 return Allow(); 376 return Allow();
278 } 377 }
279 378
280 private: 379 private:
281 DISALLOW_COPY_AND_ASSIGN(ElseIfPolicy); 380 DISALLOW_COPY_AND_ASSIGN(ElseIfPolicy);
282 }; 381 };
283 382
284 BPF_TEST_C(BPFDSL, ElseIfTest, ElseIfPolicy) { 383 TEST(BPFDSL, ElseIfTest) {
285 ASSERT_SYSCALL_RESULT(0, setuid, 0); 384 ElseIfPolicy policy;
385 PolicyEmulator emulator(&policy);
286 386
287 ASSERT_SYSCALL_RESULT(-EINVAL, setuid, 0x0001); 387 emulator.ExpectErrno(0, FakeSyscall(__NR_setuid, 0));
288 ASSERT_SYSCALL_RESULT(-EINVAL, setuid, 0x0002);
289 388
290 ASSERT_SYSCALL_RESULT(-EEXIST, setuid, 0x0011); 389 emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_setuid, 0x0001));
291 ASSERT_SYSCALL_RESULT(-EEXIST, setuid, 0x0022); 390 emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_setuid, 0x0002));
292 391
293 ASSERT_SYSCALL_RESULT(-EACCES, setuid, 0x0111); 392 emulator.ExpectErrno(EEXIST, FakeSyscall(__NR_setuid, 0x0011));
294 ASSERT_SYSCALL_RESULT(-EACCES, setuid, 0x0222); 393 emulator.ExpectErrno(EEXIST, FakeSyscall(__NR_setuid, 0x0022));
394
395 emulator.ExpectErrno(EACCES, FakeSyscall(__NR_setuid, 0x0111));
396 emulator.ExpectErrno(EACCES, FakeSyscall(__NR_setuid, 0x0222));
295 } 397 }
296 398
297 class SwitchPolicy : public Policy { 399 class SwitchPolicy : public Policy {
298 public: 400 public:
299 SwitchPolicy() {} 401 SwitchPolicy() {}
300 ~SwitchPolicy() override {} 402 ~SwitchPolicy() override {}
301 ResultExpr EvaluateSyscall(int sysno) const override { 403 ResultExpr EvaluateSyscall(int sysno) const override {
302 if (sysno == __NR_fcntl) { 404 if (sysno == __NR_fcntl) {
303 const Arg<int> cmd(1); 405 const Arg<int> cmd(1);
304 const Arg<unsigned long> long_arg(2); 406 const Arg<unsigned long> long_arg(2);
305 return Switch(cmd) 407 return Switch(cmd)
306 .CASES((F_GETFL, F_GETFD), Error(ENOENT)) 408 .CASES((F_GETFL, F_GETFD), Error(ENOENT))
307 .Case(F_SETFD, If(long_arg == O_CLOEXEC, Allow()).Else(Error(EINVAL))) 409 .Case(F_SETFD, If(long_arg == O_CLOEXEC, Allow()).Else(Error(EINVAL)))
308 .Case(F_SETFL, Error(EPERM)) 410 .Case(F_SETFL, Error(EPERM))
309 .Default(Error(EACCES)); 411 .Default(Error(EACCES));
310 } 412 }
311 return Allow(); 413 return Allow();
312 } 414 }
313 415
314 private: 416 private:
315 DISALLOW_COPY_AND_ASSIGN(SwitchPolicy); 417 DISALLOW_COPY_AND_ASSIGN(SwitchPolicy);
316 }; 418 };
317 419
318 BPF_TEST_C(BPFDSL, SwitchTest, SwitchPolicy) { 420 TEST(BPFDSL, SwitchTest) {
319 base::ScopedFD sock_fd(socket(AF_UNIX, SOCK_STREAM, 0)); 421 SwitchPolicy policy;
320 BPF_ASSERT(sock_fd.is_valid()); 422 PolicyEmulator emulator(&policy);
321 423
322 ASSERT_SYSCALL_RESULT(-ENOENT, fcntl, sock_fd.get(), F_GETFD); 424 const int kFakeSockFD = 42;
323 ASSERT_SYSCALL_RESULT(-ENOENT, fcntl, sock_fd.get(), F_GETFL);
324 425
325 ASSERT_SYSCALL_RESULT(0, fcntl, sock_fd.get(), F_SETFD, O_CLOEXEC); 426 emulator.ExpectErrno(ENOENT, FakeSyscall(__NR_fcntl, kFakeSockFD, F_GETFD));
326 ASSERT_SYSCALL_RESULT(-EINVAL, fcntl, sock_fd.get(), F_SETFD, 0); 427 emulator.ExpectErrno(ENOENT, FakeSyscall(__NR_fcntl, kFakeSockFD, F_GETFL));
327 428
328 ASSERT_SYSCALL_RESULT(-EPERM, fcntl, sock_fd.get(), F_SETFL, O_RDONLY); 429 emulator.ExpectAllow(
430 FakeSyscall(__NR_fcntl, kFakeSockFD, F_SETFD, O_CLOEXEC));
431 emulator.ExpectErrno(EINVAL,
432 FakeSyscall(__NR_fcntl, kFakeSockFD, F_SETFD, 0));
329 433
330 ASSERT_SYSCALL_RESULT(-EACCES, fcntl, sock_fd.get(), F_DUPFD, 0); 434 emulator.ExpectErrno(EPERM,
435 FakeSyscall(__NR_fcntl, kFakeSockFD, F_SETFL, O_RDONLY));
436
437 emulator.ExpectErrno(EACCES,
438 FakeSyscall(__NR_fcntl, kFakeSockFD, F_DUPFD, 0));
331 } 439 }
332 440
333 static intptr_t DummyTrap(const struct arch_seccomp_data& data, void* aux) { 441 static intptr_t DummyTrap(const struct arch_seccomp_data& data, void* aux) {
334 return 0; 442 return 0;
335 } 443 }
336 444
337 TEST(BPFDSL, IsAllowDeny) { 445 TEST(BPFDSL, IsAllowDeny) {
338 ResultExpr allow = Allow(); 446 ResultExpr allow = Allow();
339 EXPECT_TRUE(allow->IsAllow()); 447 EXPECT_TRUE(allow->IsAllow());
340 EXPECT_FALSE(allow->IsDeny()); 448 EXPECT_FALSE(allow->IsDeny());
(...skipping 27 matching lines...) Expand all
368 EXPECT_TRUE(unsafe->HasUnsafeTraps()); 476 EXPECT_TRUE(unsafe->HasUnsafeTraps());
369 477
370 const Arg<int> arg(0); 478 const Arg<int> arg(0);
371 ResultExpr maybe = If(arg == 0, allow).Else(unsafe); 479 ResultExpr maybe = If(arg == 0, allow).Else(unsafe);
372 EXPECT_TRUE(maybe->HasUnsafeTraps()); 480 EXPECT_TRUE(maybe->HasUnsafeTraps());
373 } 481 }
374 482
375 } // namespace 483 } // namespace
376 } // namespace bpf_dsl 484 } // namespace bpf_dsl
377 } // namespace sandbox 485 } // namespace sandbox
OLDNEW
« no previous file with comments | « sandbox/linux/BUILD.gn ('k') | sandbox/linux/bpf_dsl/policy_compiler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698