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

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

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

Powered by Google App Engine
This is Rietveld 408576698