OLD | NEW |
---|---|
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 #include <errno.h> | 5 #include <errno.h> |
6 #include <pthread.h> | 6 #include <pthread.h> |
7 #include <sched.h> | 7 #include <sched.h> |
8 #include <sys/prctl.h> | 8 #include <sys/prctl.h> |
9 #include <sys/syscall.h> | 9 #include <sys/syscall.h> |
10 #include <sys/time.h> | 10 #include <sys/time.h> |
(...skipping 22 matching lines...) Expand all Loading... | |
33 | 33 |
34 // Workaround for Android's prctl.h file. | 34 // Workaround for Android's prctl.h file. |
35 #ifndef PR_GET_ENDIAN | 35 #ifndef PR_GET_ENDIAN |
36 #define PR_GET_ENDIAN 19 | 36 #define PR_GET_ENDIAN 19 |
37 #endif | 37 #endif |
38 #ifndef PR_CAPBSET_READ | 38 #ifndef PR_CAPBSET_READ |
39 #define PR_CAPBSET_READ 23 | 39 #define PR_CAPBSET_READ 23 |
40 #define PR_CAPBSET_DROP 24 | 40 #define PR_CAPBSET_DROP 24 |
41 #endif | 41 #endif |
42 | 42 |
43 using namespace playground2; | 43 namespace sandbox { |
44 using sandbox::BrokerProcess; | |
45 | 44 |
46 namespace { | 45 namespace { |
47 | 46 |
48 const int kExpectedReturnValue = 42; | 47 const int kExpectedReturnValue = 42; |
49 const char kSandboxDebuggingEnv[] = "CHROME_SANDBOX_DEBUGGING"; | 48 const char kSandboxDebuggingEnv[] = "CHROME_SANDBOX_DEBUGGING"; |
50 | 49 |
51 // This test should execute no matter whether we have kernel support. So, | 50 // This test should execute no matter whether we have kernel support. So, |
52 // we make it a TEST() instead of a BPF_TEST(). | 51 // we make it a TEST() instead of a BPF_TEST(). |
53 TEST(SandboxBpf, CallSupports) { | 52 TEST(SandboxBpf, CallSupports) { |
54 // We check that we don't crash, but it's ok if the kernel doesn't | 53 // We check that we don't crash, but it's ok if the kernel doesn't |
55 // support it. | 54 // support it. |
56 bool seccomp_bpf_supported = | 55 bool seccomp_bpf_supported = |
57 Sandbox::SupportsSeccompSandbox(-1) == Sandbox::STATUS_AVAILABLE; | 56 SandboxBPF::SupportsSeccompSandbox(-1) == SandboxBPF::STATUS_AVAILABLE; |
58 // We want to log whether or not seccomp BPF is actually supported | 57 // We want to log whether or not seccomp BPF is actually supported |
59 // since actual test coverage depends on it. | 58 // since actual test coverage depends on it. |
60 RecordProperty("SeccompBPFSupported", | 59 RecordProperty("SeccompBPFSupported", |
61 seccomp_bpf_supported ? "true." : "false."); | 60 seccomp_bpf_supported ? "true." : "false."); |
62 std::cout << "Seccomp BPF supported: " | 61 std::cout << "Seccomp BPF supported: " |
63 << (seccomp_bpf_supported ? "true." : "false.") << "\n"; | 62 << (seccomp_bpf_supported ? "true." : "false.") << "\n"; |
64 RecordProperty("PointerSize", sizeof(void*)); | 63 RecordProperty("PointerSize", sizeof(void*)); |
65 std::cout << "Pointer size: " << sizeof(void*) << "\n"; | 64 std::cout << "Pointer size: " << sizeof(void*) << "\n"; |
66 } | 65 } |
67 | 66 |
68 SANDBOX_TEST(SandboxBpf, CallSupportsTwice) { | 67 SANDBOX_TEST(SandboxBpf, CallSupportsTwice) { |
69 Sandbox::SupportsSeccompSandbox(-1); | 68 SandboxBPF::SupportsSeccompSandbox(-1); |
70 Sandbox::SupportsSeccompSandbox(-1); | 69 SandboxBPF::SupportsSeccompSandbox(-1); |
71 } | 70 } |
72 | 71 |
73 // BPF_TEST does a lot of the boiler-plate code around setting up a | 72 // BPF_TEST does a lot of the boiler-plate code around setting up a |
74 // policy and optional passing data between the caller, the policy and | 73 // policy and optional passing data between the caller, the policy and |
75 // any Trap() handlers. This is great for writing short and concise tests, | 74 // any Trap() handlers. This is great for writing short and concise tests, |
76 // and it helps us accidentally forgetting any of the crucial steps in | 75 // and it helps us accidentally forgetting any of the crucial steps in |
77 // setting up the sandbox. But it wouldn't hurt to have at least one test | 76 // setting up the sandbox. But it wouldn't hurt to have at least one test |
78 // that explicitly walks through all these steps. | 77 // that explicitly walks through all these steps. |
79 | 78 |
80 intptr_t FakeGetPid(const struct arch_seccomp_data& args, void* aux) { | 79 intptr_t FakeGetPid(const struct arch_seccomp_data& args, void* aux) { |
81 BPF_ASSERT(aux); | 80 BPF_ASSERT(aux); |
82 pid_t* pid_ptr = static_cast<pid_t*>(aux); | 81 pid_t* pid_ptr = static_cast<pid_t*>(aux); |
83 return (*pid_ptr)++; | 82 return (*pid_ptr)++; |
84 } | 83 } |
85 | 84 |
86 ErrorCode VerboseAPITestingPolicy(Sandbox* sandbox, int sysno, void* aux) { | 85 ErrorCode VerboseAPITestingPolicy(SandboxBPF* sandbox, int sysno, void* aux) { |
87 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 86 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
88 return ErrorCode(ENOSYS); | 87 return ErrorCode(ENOSYS); |
89 } else if (sysno == __NR_getpid) { | 88 } else if (sysno == __NR_getpid) { |
90 return sandbox->Trap(FakeGetPid, aux); | 89 return sandbox->Trap(FakeGetPid, aux); |
91 } else { | 90 } else { |
92 return ErrorCode(ErrorCode::ERR_ALLOWED); | 91 return ErrorCode(ErrorCode::ERR_ALLOWED); |
93 } | 92 } |
94 } | 93 } |
95 | 94 |
96 SANDBOX_TEST(SandboxBpf, DISABLE_ON_TSAN(VerboseAPITesting)) { | 95 SANDBOX_TEST(SandboxBpf, DISABLE_ON_TSAN(VerboseAPITesting)) { |
97 if (Sandbox::SupportsSeccompSandbox(-1) == | 96 if (SandboxBPF::SupportsSeccompSandbox(-1) == |
98 playground2::Sandbox::STATUS_AVAILABLE) { | 97 sandbox::SandboxBPF::STATUS_AVAILABLE) { |
99 pid_t test_var = 0; | 98 pid_t test_var = 0; |
100 Sandbox sandbox; | 99 SandboxBPF sandbox; |
101 sandbox.SetSandboxPolicyDeprecated(VerboseAPITestingPolicy, &test_var); | 100 sandbox.SetSandboxPolicyDeprecated(VerboseAPITestingPolicy, &test_var); |
102 sandbox.StartSandbox(); | 101 sandbox.StartSandbox(); |
103 | 102 |
104 BPF_ASSERT(test_var == 0); | 103 BPF_ASSERT(test_var == 0); |
105 BPF_ASSERT(syscall(__NR_getpid) == 0); | 104 BPF_ASSERT(syscall(__NR_getpid) == 0); |
106 BPF_ASSERT(test_var == 1); | 105 BPF_ASSERT(test_var == 1); |
107 BPF_ASSERT(syscall(__NR_getpid) == 1); | 106 BPF_ASSERT(syscall(__NR_getpid) == 1); |
108 BPF_ASSERT(test_var == 2); | 107 BPF_ASSERT(test_var == 2); |
109 | 108 |
110 // N.B.: Any future call to getpid() would corrupt the stack. | 109 // N.B.: Any future call to getpid() would corrupt the stack. |
111 // This is OK. The SANDBOX_TEST() macro is guaranteed to | 110 // This is OK. The SANDBOX_TEST() macro is guaranteed to |
112 // only ever call _exit() after the test completes. | 111 // only ever call _exit() after the test completes. |
113 } | 112 } |
114 } | 113 } |
115 | 114 |
116 // A simple blacklist test | 115 // A simple blacklist test |
117 | 116 |
118 ErrorCode BlacklistNanosleepPolicy(Sandbox*, int sysno, void*) { | 117 ErrorCode BlacklistNanosleepPolicy(SandboxBPF*, int sysno, void*) { |
119 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 118 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
120 // FIXME: we should really not have to do that in a trivial policy | 119 // FIXME: we should really not have to do that in a trivial policy |
121 return ErrorCode(ENOSYS); | 120 return ErrorCode(ENOSYS); |
122 } | 121 } |
123 | 122 |
124 switch (sysno) { | 123 switch (sysno) { |
125 case __NR_nanosleep: | 124 case __NR_nanosleep: |
126 return ErrorCode(EACCES); | 125 return ErrorCode(EACCES); |
127 default: | 126 default: |
128 return ErrorCode(ErrorCode::ERR_ALLOWED); | 127 return ErrorCode(ErrorCode::ERR_ALLOWED); |
129 } | 128 } |
130 } | 129 } |
131 | 130 |
132 BPF_TEST(SandboxBpf, ApplyBasicBlacklistPolicy, BlacklistNanosleepPolicy) { | 131 BPF_TEST(SandboxBpf, ApplyBasicBlacklistPolicy, BlacklistNanosleepPolicy) { |
133 // nanosleep() should be denied | 132 // nanosleep() should be denied |
134 const struct timespec ts = {0, 0}; | 133 const struct timespec ts = {0, 0}; |
135 errno = 0; | 134 errno = 0; |
136 BPF_ASSERT(syscall(__NR_nanosleep, &ts, NULL) == -1); | 135 BPF_ASSERT(syscall(__NR_nanosleep, &ts, NULL) == -1); |
137 BPF_ASSERT(errno == EACCES); | 136 BPF_ASSERT(errno == EACCES); |
138 } | 137 } |
139 | 138 |
140 // Now do a simple whitelist test | 139 // Now do a simple whitelist test |
141 | 140 |
142 ErrorCode WhitelistGetpidPolicy(Sandbox*, int sysno, void*) { | 141 ErrorCode WhitelistGetpidPolicy(SandboxBPF*, int sysno, void*) { |
143 switch (sysno) { | 142 switch (sysno) { |
144 case __NR_getpid: | 143 case __NR_getpid: |
145 case __NR_exit_group: | 144 case __NR_exit_group: |
146 return ErrorCode(ErrorCode::ERR_ALLOWED); | 145 return ErrorCode(ErrorCode::ERR_ALLOWED); |
147 default: | 146 default: |
148 return ErrorCode(ENOMEM); | 147 return ErrorCode(ENOMEM); |
149 } | 148 } |
150 } | 149 } |
151 | 150 |
152 BPF_TEST(SandboxBpf, ApplyBasicWhitelistPolicy, WhitelistGetpidPolicy) { | 151 BPF_TEST(SandboxBpf, ApplyBasicWhitelistPolicy, WhitelistGetpidPolicy) { |
153 // getpid() should be allowed | 152 // getpid() should be allowed |
154 errno = 0; | 153 errno = 0; |
155 BPF_ASSERT(syscall(__NR_getpid) > 0); | 154 BPF_ASSERT(syscall(__NR_getpid) > 0); |
156 BPF_ASSERT(errno == 0); | 155 BPF_ASSERT(errno == 0); |
157 | 156 |
158 // getpgid() should be denied | 157 // getpgid() should be denied |
159 BPF_ASSERT(getpgid(0) == -1); | 158 BPF_ASSERT(getpgid(0) == -1); |
160 BPF_ASSERT(errno == ENOMEM); | 159 BPF_ASSERT(errno == ENOMEM); |
161 } | 160 } |
162 | 161 |
163 // A simple blacklist policy, with a SIGSYS handler | 162 // A simple blacklist policy, with a SIGSYS handler |
164 | 163 |
165 intptr_t EnomemHandler(const struct arch_seccomp_data& args, void* aux) { | 164 intptr_t EnomemHandler(const struct arch_seccomp_data& args, void* aux) { |
166 // We also check that the auxiliary data is correct | 165 // We also check that the auxiliary data is correct |
167 SANDBOX_ASSERT(aux); | 166 SANDBOX_ASSERT(aux); |
168 *(static_cast<int*>(aux)) = kExpectedReturnValue; | 167 *(static_cast<int*>(aux)) = kExpectedReturnValue; |
169 return -ENOMEM; | 168 return -ENOMEM; |
170 } | 169 } |
171 | 170 |
172 ErrorCode BlacklistNanosleepPolicySigsys(Sandbox* sandbox, | 171 ErrorCode BlacklistNanosleepPolicySigsys(SandboxBPF* sandbox, |
173 int sysno, | 172 int sysno, |
174 void* aux) { | 173 void* aux) { |
175 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 174 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
176 // FIXME: we should really not have to do that in a trivial policy | 175 // FIXME: we should really not have to do that in a trivial policy |
177 return ErrorCode(ENOSYS); | 176 return ErrorCode(ENOSYS); |
178 } | 177 } |
179 | 178 |
180 switch (sysno) { | 179 switch (sysno) { |
181 case __NR_nanosleep: | 180 case __NR_nanosleep: |
182 return sandbox->Trap(EnomemHandler, aux); | 181 return sandbox->Trap(EnomemHandler, aux); |
183 default: | 182 default: |
184 return ErrorCode(ErrorCode::ERR_ALLOWED); | 183 return ErrorCode(ErrorCode::ERR_ALLOWED); |
185 } | 184 } |
(...skipping 13 matching lines...) Expand all Loading... | |
199 const struct timespec ts = {0, 0}; | 198 const struct timespec ts = {0, 0}; |
200 BPF_ASSERT(syscall(__NR_nanosleep, &ts, NULL) == -1); | 199 BPF_ASSERT(syscall(__NR_nanosleep, &ts, NULL) == -1); |
201 BPF_ASSERT(errno == ENOMEM); | 200 BPF_ASSERT(errno == ENOMEM); |
202 | 201 |
203 // We expect the signal handler to modify AuxData | 202 // We expect the signal handler to modify AuxData |
204 BPF_ASSERT(BPF_AUX == kExpectedReturnValue); | 203 BPF_ASSERT(BPF_AUX == kExpectedReturnValue); |
205 } | 204 } |
206 | 205 |
207 // A simple test that verifies we can return arbitrary errno values. | 206 // A simple test that verifies we can return arbitrary errno values. |
208 | 207 |
209 ErrorCode ErrnoTestPolicy(Sandbox*, int sysno, void*) { | 208 ErrorCode ErrnoTestPolicy(SandboxBPF*, int sysno, void*) { |
210 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 209 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
211 // FIXME: we should really not have to do that in a trivial policy | 210 // FIXME: we should really not have to do that in a trivial policy |
212 return ErrorCode(ENOSYS); | 211 return ErrorCode(ENOSYS); |
213 } | 212 } |
214 | 213 |
215 switch (sysno) { | 214 switch (sysno) { |
216 case __NR_dup2: | 215 case __NR_dup2: |
217 // Pretend that dup2() worked, but don't actually do anything. | 216 // Pretend that dup2() worked, but don't actually do anything. |
218 return ErrorCode(0); | 217 return ErrorCode(0); |
219 case __NR_setuid: | 218 case __NR_setuid: |
220 #if defined(__NR_setuid32) | 219 #if defined(__NR_setuid32) |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
271 | 270 |
272 // Finally, test an errno in between the minimum and maximum. | 271 // Finally, test an errno in between the minimum and maximum. |
273 errno = 0; | 272 errno = 0; |
274 struct utsname uts_buf; | 273 struct utsname uts_buf; |
275 BPF_ASSERT(uname(&uts_buf) == -1); | 274 BPF_ASSERT(uname(&uts_buf) == -1); |
276 BPF_ASSERT(errno == 42); | 275 BPF_ASSERT(errno == 42); |
277 } | 276 } |
278 | 277 |
279 // Testing the stacking of two sandboxes | 278 // Testing the stacking of two sandboxes |
280 | 279 |
281 ErrorCode StackingPolicyPartOne(Sandbox* sandbox, int sysno, void*) { | 280 ErrorCode StackingPolicyPartOne(SandboxBPF* sandbox, int sysno, void*) { |
282 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 281 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
283 return ErrorCode(ENOSYS); | 282 return ErrorCode(ENOSYS); |
284 } | 283 } |
285 | 284 |
286 switch (sysno) { | 285 switch (sysno) { |
287 case __NR_getppid: | 286 case __NR_getppid: |
288 return sandbox->Cond(0, | 287 return sandbox->Cond(0, |
289 ErrorCode::TP_32BIT, | 288 ErrorCode::TP_32BIT, |
290 ErrorCode::OP_EQUAL, | 289 ErrorCode::OP_EQUAL, |
291 0, | 290 0, |
292 ErrorCode(ErrorCode::ERR_ALLOWED), | 291 ErrorCode(ErrorCode::ERR_ALLOWED), |
293 ErrorCode(EPERM)); | 292 ErrorCode(EPERM)); |
294 default: | 293 default: |
295 return ErrorCode(ErrorCode::ERR_ALLOWED); | 294 return ErrorCode(ErrorCode::ERR_ALLOWED); |
296 } | 295 } |
297 } | 296 } |
298 | 297 |
299 ErrorCode StackingPolicyPartTwo(Sandbox* sandbox, int sysno, void*) { | 298 ErrorCode StackingPolicyPartTwo(SandboxBPF* sandbox, int sysno, void*) { |
300 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 299 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
301 return ErrorCode(ENOSYS); | 300 return ErrorCode(ENOSYS); |
302 } | 301 } |
303 | 302 |
304 switch (sysno) { | 303 switch (sysno) { |
305 case __NR_getppid: | 304 case __NR_getppid: |
306 return sandbox->Cond(0, | 305 return sandbox->Cond(0, |
307 ErrorCode::TP_32BIT, | 306 ErrorCode::TP_32BIT, |
308 ErrorCode::OP_EQUAL, | 307 ErrorCode::OP_EQUAL, |
309 0, | 308 0, |
310 ErrorCode(EINVAL), | 309 ErrorCode(EINVAL), |
311 ErrorCode(ErrorCode::ERR_ALLOWED)); | 310 ErrorCode(ErrorCode::ERR_ALLOWED)); |
312 default: | 311 default: |
313 return ErrorCode(ErrorCode::ERR_ALLOWED); | 312 return ErrorCode(ErrorCode::ERR_ALLOWED); |
314 } | 313 } |
315 } | 314 } |
316 | 315 |
317 BPF_TEST(SandboxBpf, StackingPolicy, StackingPolicyPartOne) { | 316 BPF_TEST(SandboxBpf, StackingPolicy, StackingPolicyPartOne) { |
318 errno = 0; | 317 errno = 0; |
319 BPF_ASSERT(syscall(__NR_getppid, 0) > 0); | 318 BPF_ASSERT(syscall(__NR_getppid, 0) > 0); |
320 BPF_ASSERT(errno == 0); | 319 BPF_ASSERT(errno == 0); |
321 | 320 |
322 BPF_ASSERT(syscall(__NR_getppid, 1) == -1); | 321 BPF_ASSERT(syscall(__NR_getppid, 1) == -1); |
323 BPF_ASSERT(errno == EPERM); | 322 BPF_ASSERT(errno == EPERM); |
324 | 323 |
325 // Stack a second sandbox with its own policy. Verify that we can further | 324 // Stack a second sandbox with its own policy. Verify that we can further |
326 // restrict filters, but we cannot relax existing filters. | 325 // restrict filters, but we cannot relax existing filters. |
327 Sandbox sandbox; | 326 SandboxBPF sandbox; |
328 sandbox.SetSandboxPolicyDeprecated(StackingPolicyPartTwo, NULL); | 327 sandbox.SetSandboxPolicyDeprecated(StackingPolicyPartTwo, NULL); |
329 sandbox.StartSandbox(); | 328 sandbox.StartSandbox(); |
330 | 329 |
331 errno = 0; | 330 errno = 0; |
332 BPF_ASSERT(syscall(__NR_getppid, 0) == -1); | 331 BPF_ASSERT(syscall(__NR_getppid, 0) == -1); |
333 BPF_ASSERT(errno == EINVAL); | 332 BPF_ASSERT(errno == EINVAL); |
334 | 333 |
335 BPF_ASSERT(syscall(__NR_getppid, 1) == -1); | 334 BPF_ASSERT(syscall(__NR_getppid, 1) == -1); |
336 BPF_ASSERT(errno == EPERM); | 335 BPF_ASSERT(errno == EPERM); |
337 } | 336 } |
338 | 337 |
339 // A more complex, but synthetic policy. This tests the correctness of the BPF | 338 // A more complex, but synthetic policy. This tests the correctness of the BPF |
340 // program by iterating through all syscalls and checking for an errno that | 339 // program by iterating through all syscalls and checking for an errno that |
341 // depends on the syscall number. Unlike the Verifier, this exercises the BPF | 340 // depends on the syscall number. Unlike the Verifier, this exercises the BPF |
342 // interpreter in the kernel. | 341 // interpreter in the kernel. |
343 | 342 |
344 // We try to make sure we exercise optimizations in the BPF compiler. We make | 343 // We try to make sure we exercise optimizations in the BPF compiler. We make |
345 // sure that the compiler can have an opportunity to coalesce syscalls with | 344 // sure that the compiler can have an opportunity to coalesce syscalls with |
346 // contiguous numbers and we also make sure that disjoint sets can return the | 345 // contiguous numbers and we also make sure that disjoint sets can return the |
347 // same errno. | 346 // same errno. |
348 int SysnoToRandomErrno(int sysno) { | 347 int SysnoToRandomErrno(int sysno) { |
349 // Small contiguous sets of 3 system calls return an errno equal to the | 348 // Small contiguous sets of 3 system calls return an errno equal to the |
350 // index of that set + 1 (so that we never return a NUL errno). | 349 // index of that set + 1 (so that we never return a NUL errno). |
351 return ((sysno & ~3) >> 2) % 29 + 1; | 350 return ((sysno & ~3) >> 2) % 29 + 1; |
352 } | 351 } |
353 | 352 |
354 ErrorCode SyntheticPolicy(Sandbox*, int sysno, void*) { | 353 ErrorCode SyntheticPolicy(SandboxBPF*, int sysno, void*) { |
355 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 354 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
356 // FIXME: we should really not have to do that in a trivial policy | 355 // FIXME: we should really not have to do that in a trivial policy |
357 return ErrorCode(ENOSYS); | 356 return ErrorCode(ENOSYS); |
358 } | 357 } |
359 | 358 |
360 // TODO(jorgelo): remove this once the new code generator lands. | 359 // TODO(jorgelo): remove this once the new code generator lands. |
361 #if defined(__arm__) | 360 #if defined(__arm__) |
362 if (sysno > static_cast<int>(MAX_PUBLIC_SYSCALL)) { | 361 if (sysno > static_cast<int>(MAX_PUBLIC_SYSCALL)) { |
363 return ErrorCode(ENOSYS); | 362 return ErrorCode(ENOSYS); |
364 } | 363 } |
365 #endif | 364 #endif |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
400 // MIN_PRIVATE_SYSCALL plus 1 (to avoid NUL errno). | 399 // MIN_PRIVATE_SYSCALL plus 1 (to avoid NUL errno). |
401 int ArmPrivateSysnoToErrno(int sysno) { | 400 int ArmPrivateSysnoToErrno(int sysno) { |
402 if (sysno >= static_cast<int>(MIN_PRIVATE_SYSCALL) && | 401 if (sysno >= static_cast<int>(MIN_PRIVATE_SYSCALL) && |
403 sysno <= static_cast<int>(MAX_PRIVATE_SYSCALL)) { | 402 sysno <= static_cast<int>(MAX_PRIVATE_SYSCALL)) { |
404 return (sysno - MIN_PRIVATE_SYSCALL) + 1; | 403 return (sysno - MIN_PRIVATE_SYSCALL) + 1; |
405 } else { | 404 } else { |
406 return ENOSYS; | 405 return ENOSYS; |
407 } | 406 } |
408 } | 407 } |
409 | 408 |
410 ErrorCode ArmPrivatePolicy(Sandbox*, int sysno, void*) { | 409 ErrorCode ArmPrivatePolicy(SandboxBPF*, int sysno, void*) { |
411 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 410 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
412 // FIXME: we should really not have to do that in a trivial policy. | 411 // FIXME: we should really not have to do that in a trivial policy. |
413 return ErrorCode(ENOSYS); | 412 return ErrorCode(ENOSYS); |
414 } | 413 } |
415 | 414 |
416 // Start from |__ARM_NR_set_tls + 1| so as not to mess with actual | 415 // Start from |__ARM_NR_set_tls + 1| so as not to mess with actual |
417 // ARM private system calls. | 416 // ARM private system calls. |
418 if (sysno >= static_cast<int>(__ARM_NR_set_tls + 1) && | 417 if (sysno >= static_cast<int>(__ARM_NR_set_tls + 1) && |
419 sysno <= static_cast<int>(MAX_PRIVATE_SYSCALL)) { | 418 sysno <= static_cast<int>(MAX_PRIVATE_SYSCALL)) { |
420 return ErrorCode(ArmPrivateSysnoToErrno(sysno)); | 419 return ErrorCode(ArmPrivateSysnoToErrno(sysno)); |
421 } else { | 420 } else { |
(...skipping 15 matching lines...) Expand all Loading... | |
437 intptr_t CountSyscalls(const struct arch_seccomp_data& args, void* aux) { | 436 intptr_t CountSyscalls(const struct arch_seccomp_data& args, void* aux) { |
438 // Count all invocations of our callback function. | 437 // Count all invocations of our callback function. |
439 ++*reinterpret_cast<int*>(aux); | 438 ++*reinterpret_cast<int*>(aux); |
440 | 439 |
441 // Verify that within the callback function all filtering is temporarily | 440 // Verify that within the callback function all filtering is temporarily |
442 // disabled. | 441 // disabled. |
443 BPF_ASSERT(syscall(__NR_getpid) > 1); | 442 BPF_ASSERT(syscall(__NR_getpid) > 1); |
444 | 443 |
445 // Verify that we can now call the underlying system call without causing | 444 // Verify that we can now call the underlying system call without causing |
446 // infinite recursion. | 445 // infinite recursion. |
447 return Sandbox::ForwardSyscall(args); | 446 return SandboxBPF::ForwardSyscall(args); |
448 } | 447 } |
449 | 448 |
450 ErrorCode GreyListedPolicy(Sandbox* sandbox, int sysno, void* aux) { | 449 ErrorCode GreyListedPolicy(SandboxBPF* sandbox, int sysno, void* aux) { |
451 // The use of UnsafeTrap() causes us to print a warning message. This is | 450 // The use of UnsafeTrap() causes us to print a warning message. This is |
452 // generally desirable, but it results in the unittest failing, as it doesn't | 451 // generally desirable, but it results in the unittest failing, as it doesn't |
453 // expect any messages on "stderr". So, temporarily disable messages. The | 452 // expect any messages on "stderr". So, temporarily disable messages. The |
454 // BPF_TEST() is guaranteed to turn messages back on, after the policy | 453 // BPF_TEST() is guaranteed to turn messages back on, after the policy |
455 // function has completed. | 454 // function has completed. |
456 setenv(kSandboxDebuggingEnv, "t", 0); | 455 setenv(kSandboxDebuggingEnv, "t", 0); |
457 Die::SuppressInfoMessages(true); | 456 Die::SuppressInfoMessages(true); |
458 | 457 |
459 // Some system calls must always be allowed, if our policy wants to make | 458 // Some system calls must always be allowed, if our policy wants to make |
460 // use of UnsafeTrap() | 459 // use of UnsafeTrap() |
461 if (sysno == __NR_rt_sigprocmask || sysno == __NR_rt_sigreturn | 460 if (sysno == __NR_rt_sigprocmask || sysno == __NR_rt_sigreturn |
462 #if defined(__NR_sigprocmask) | 461 #if defined(__NR_sigprocmask) |
463 || | 462 || |
464 sysno == __NR_sigprocmask | 463 sysno == __NR_sigprocmask |
465 #endif | 464 #endif |
466 #if defined(__NR_sigreturn) | 465 #if defined(__NR_sigreturn) |
467 || | 466 || |
468 sysno == __NR_sigreturn | 467 sysno == __NR_sigreturn |
469 #endif | 468 #endif |
470 ) { | 469 ) { |
471 return ErrorCode(ErrorCode::ERR_ALLOWED); | 470 return ErrorCode(ErrorCode::ERR_ALLOWED); |
472 } else if (sysno == __NR_getpid) { | 471 } else if (sysno == __NR_getpid) { |
473 // Disallow getpid() | 472 // Disallow getpid() |
474 return ErrorCode(EPERM); | 473 return ErrorCode(EPERM); |
475 } else if (Sandbox::IsValidSyscallNumber(sysno)) { | 474 } else if (SandboxBPF::IsValidSyscallNumber(sysno)) { |
476 // Allow (and count) all other system calls. | 475 // Allow (and count) all other system calls. |
477 return sandbox->UnsafeTrap(CountSyscalls, aux); | 476 return sandbox->UnsafeTrap(CountSyscalls, aux); |
478 } else { | 477 } else { |
479 return ErrorCode(ENOSYS); | 478 return ErrorCode(ENOSYS); |
480 } | 479 } |
481 } | 480 } |
482 | 481 |
483 BPF_TEST(SandboxBpf, GreyListedPolicy, GreyListedPolicy, int /* BPF_AUX */) { | 482 BPF_TEST(SandboxBpf, GreyListedPolicy, GreyListedPolicy, int /* BPF_AUX */) { |
484 BPF_ASSERT(syscall(__NR_getpid) == -1); | 483 BPF_ASSERT(syscall(__NR_getpid) == -1); |
485 BPF_ASSERT(errno == EPERM); | 484 BPF_ASSERT(errno == EPERM); |
(...skipping 23 matching lines...) Expand all Loading... | |
509 setenv(kSandboxDebuggingEnv, "t", 1); | 508 setenv(kSandboxDebuggingEnv, "t", 1); |
510 SANDBOX_ASSERT(Trap::EnableUnsafeTrapsInSigSysHandler() == true); | 509 SANDBOX_ASSERT(Trap::EnableUnsafeTrapsInSigSysHandler() == true); |
511 } | 510 } |
512 | 511 |
513 intptr_t PrctlHandler(const struct arch_seccomp_data& args, void*) { | 512 intptr_t PrctlHandler(const struct arch_seccomp_data& args, void*) { |
514 if (args.args[0] == PR_CAPBSET_DROP && static_cast<int>(args.args[1]) == -1) { | 513 if (args.args[0] == PR_CAPBSET_DROP && static_cast<int>(args.args[1]) == -1) { |
515 // prctl(PR_CAPBSET_DROP, -1) is never valid. The kernel will always | 514 // prctl(PR_CAPBSET_DROP, -1) is never valid. The kernel will always |
516 // return an error. But our handler allows this call. | 515 // return an error. But our handler allows this call. |
517 return 0; | 516 return 0; |
518 } else { | 517 } else { |
519 return Sandbox::ForwardSyscall(args); | 518 return SandboxBPF::ForwardSyscall(args); |
520 } | 519 } |
521 } | 520 } |
522 | 521 |
523 ErrorCode PrctlPolicy(Sandbox* sandbox, int sysno, void* aux) { | 522 ErrorCode PrctlPolicy(SandboxBPF* sandbox, int sysno, void* aux) { |
524 setenv(kSandboxDebuggingEnv, "t", 0); | 523 setenv(kSandboxDebuggingEnv, "t", 0); |
525 Die::SuppressInfoMessages(true); | 524 Die::SuppressInfoMessages(true); |
526 | 525 |
527 if (sysno == __NR_prctl) { | 526 if (sysno == __NR_prctl) { |
528 // Handle prctl() inside an UnsafeTrap() | 527 // Handle prctl() inside an UnsafeTrap() |
529 return sandbox->UnsafeTrap(PrctlHandler, NULL); | 528 return sandbox->UnsafeTrap(PrctlHandler, NULL); |
530 } else if (Sandbox::IsValidSyscallNumber(sysno)) { | 529 } else if (SandboxBPF::IsValidSyscallNumber(sysno)) { |
531 // Allow all other system calls. | 530 // Allow all other system calls. |
532 return ErrorCode(ErrorCode::ERR_ALLOWED); | 531 return ErrorCode(ErrorCode::ERR_ALLOWED); |
533 } else { | 532 } else { |
534 return ErrorCode(ENOSYS); | 533 return ErrorCode(ENOSYS); |
535 } | 534 } |
536 } | 535 } |
537 | 536 |
538 BPF_TEST(SandboxBpf, ForwardSyscall, PrctlPolicy) { | 537 BPF_TEST(SandboxBpf, ForwardSyscall, PrctlPolicy) { |
539 // This call should never be allowed. But our policy will intercept it and | 538 // This call should never be allowed. But our policy will intercept it and |
540 // let it pass successfully. | 539 // let it pass successfully. |
(...skipping 15 matching lines...) Expand all Loading... | |
556 BPF_ASSERT(*name); | 555 BPF_ASSERT(*name); |
557 | 556 |
558 // Finally, verify that system calls other than prctl() are completely | 557 // Finally, verify that system calls other than prctl() are completely |
559 // unaffected by our policy. | 558 // unaffected by our policy. |
560 struct utsname uts = {}; | 559 struct utsname uts = {}; |
561 BPF_ASSERT(!uname(&uts)); | 560 BPF_ASSERT(!uname(&uts)); |
562 BPF_ASSERT(!strcmp(uts.sysname, "Linux")); | 561 BPF_ASSERT(!strcmp(uts.sysname, "Linux")); |
563 } | 562 } |
564 | 563 |
565 intptr_t AllowRedirectedSyscall(const struct arch_seccomp_data& args, void*) { | 564 intptr_t AllowRedirectedSyscall(const struct arch_seccomp_data& args, void*) { |
566 return Sandbox::ForwardSyscall(args); | 565 return SandboxBPF::ForwardSyscall(args); |
567 } | 566 } |
568 | 567 |
569 ErrorCode RedirectAllSyscallsPolicy(Sandbox* sandbox, int sysno, void* aux) { | 568 ErrorCode RedirectAllSyscallsPolicy(SandboxBPF* sandbox, int sysno, void* aux) { |
570 setenv(kSandboxDebuggingEnv, "t", 0); | 569 setenv(kSandboxDebuggingEnv, "t", 0); |
571 Die::SuppressInfoMessages(true); | 570 Die::SuppressInfoMessages(true); |
572 | 571 |
573 // Some system calls must always be allowed, if our policy wants to make | 572 // Some system calls must always be allowed, if our policy wants to make |
574 // use of UnsafeTrap() | 573 // use of UnsafeTrap() |
575 if (sysno == __NR_rt_sigprocmask || sysno == __NR_rt_sigreturn | 574 if (sysno == __NR_rt_sigprocmask || sysno == __NR_rt_sigreturn |
576 #if defined(__NR_sigprocmask) | 575 #if defined(__NR_sigprocmask) |
577 || | 576 || |
578 sysno == __NR_sigprocmask | 577 sysno == __NR_sigprocmask |
579 #endif | 578 #endif |
580 #if defined(__NR_sigreturn) | 579 #if defined(__NR_sigreturn) |
581 || | 580 || |
582 sysno == __NR_sigreturn | 581 sysno == __NR_sigreturn |
583 #endif | 582 #endif |
584 ) { | 583 ) { |
585 return ErrorCode(ErrorCode::ERR_ALLOWED); | 584 return ErrorCode(ErrorCode::ERR_ALLOWED); |
586 } else if (Sandbox::IsValidSyscallNumber(sysno)) { | 585 } else if (SandboxBPF::IsValidSyscallNumber(sysno)) { |
587 return sandbox->UnsafeTrap(AllowRedirectedSyscall, aux); | 586 return sandbox->UnsafeTrap(AllowRedirectedSyscall, aux); |
588 } else { | 587 } else { |
589 return ErrorCode(ENOSYS); | 588 return ErrorCode(ENOSYS); |
590 } | 589 } |
591 } | 590 } |
592 | 591 |
593 int bus_handler_fd_ = -1; | 592 int bus_handler_fd_ = -1; |
594 | 593 |
595 void SigBusHandler(int, siginfo_t* info, void* void_context) { | 594 void SigBusHandler(int, siginfo_t* info, void* void_context) { |
596 BPF_ASSERT(write(bus_handler_fd_, "\x55", 1) == 1); | 595 BPF_ASSERT(write(bus_handler_fd_, "\x55", 1) == 1); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
660 BPF_ASSERT(close(-1) == -1); | 659 BPF_ASSERT(close(-1) == -1); |
661 BPF_ASSERT(errno == EBADF); | 660 BPF_ASSERT(errno == EBADF); |
662 | 661 |
663 // Explicitly avoid the glibc wrapper. This is not normally the way anybody | 662 // Explicitly avoid the glibc wrapper. This is not normally the way anybody |
664 // would make system calls, but it allows us to verify that we don't | 663 // would make system calls, but it allows us to verify that we don't |
665 // accidentally mess with errno, when we shouldn't. | 664 // accidentally mess with errno, when we shouldn't. |
666 errno = 0; | 665 errno = 0; |
667 struct arch_seccomp_data args = {}; | 666 struct arch_seccomp_data args = {}; |
668 args.nr = __NR_close; | 667 args.nr = __NR_close; |
669 args.args[0] = -1; | 668 args.args[0] = -1; |
670 BPF_ASSERT(Sandbox::ForwardSyscall(args) == -EBADF); | 669 BPF_ASSERT(SandboxBPF::ForwardSyscall(args) == -EBADF); |
671 BPF_ASSERT(errno == 0); | 670 BPF_ASSERT(errno == 0); |
672 } | 671 } |
673 | 672 |
674 // Test a trap handler that makes use of a broker process to open(). | 673 // Test a trap handler that makes use of a broker process to open(). |
675 | 674 |
676 class InitializedOpenBroker { | 675 class InitializedOpenBroker { |
677 public: | 676 public: |
678 InitializedOpenBroker() : initialized_(false) { | 677 InitializedOpenBroker() : initialized_(false) { |
679 std::vector<std::string> allowed_files; | 678 std::vector<std::string> allowed_files; |
680 allowed_files.push_back("/proc/allowed"); | 679 allowed_files.push_back("/proc/allowed"); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
712 // the openat() system call. | 711 // the openat() system call. |
713 BPF_ASSERT(static_cast<int>(args.args[0]) == AT_FDCWD); | 712 BPF_ASSERT(static_cast<int>(args.args[0]) == AT_FDCWD); |
714 return broker_process->Open(reinterpret_cast<const char*>(args.args[1]), | 713 return broker_process->Open(reinterpret_cast<const char*>(args.args[1]), |
715 static_cast<int>(args.args[2])); | 714 static_cast<int>(args.args[2])); |
716 default: | 715 default: |
717 BPF_ASSERT(false); | 716 BPF_ASSERT(false); |
718 return -ENOSYS; | 717 return -ENOSYS; |
719 } | 718 } |
720 } | 719 } |
721 | 720 |
722 ErrorCode DenyOpenPolicy(Sandbox* sandbox, int sysno, void* aux) { | 721 ErrorCode DenyOpenPolicy(SandboxBPF* sandbox, int sysno, void* aux) { |
723 InitializedOpenBroker* iob = static_cast<InitializedOpenBroker*>(aux); | 722 InitializedOpenBroker* iob = static_cast<InitializedOpenBroker*>(aux); |
724 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 723 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
725 return ErrorCode(ENOSYS); | 724 return ErrorCode(ENOSYS); |
726 } | 725 } |
727 | 726 |
728 switch (sysno) { | 727 switch (sysno) { |
729 case __NR_access: | 728 case __NR_access: |
730 case __NR_open: | 729 case __NR_open: |
731 case __NR_openat: | 730 case __NR_openat: |
732 // We get a InitializedOpenBroker class, but our trap handler wants | 731 // We get a InitializedOpenBroker class, but our trap handler wants |
733 // the BrokerProcess object. | 732 // the BrokerProcess object. |
734 return ErrorCode( | 733 return ErrorCode( |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
778 | 777 |
779 // This is also white listed and does exist. | 778 // This is also white listed and does exist. |
780 int cpu_info_access = access("/proc/cpuinfo", R_OK); | 779 int cpu_info_access = access("/proc/cpuinfo", R_OK); |
781 BPF_ASSERT(cpu_info_access == 0); | 780 BPF_ASSERT(cpu_info_access == 0); |
782 int cpu_info_fd = open("/proc/cpuinfo", O_RDONLY); | 781 int cpu_info_fd = open("/proc/cpuinfo", O_RDONLY); |
783 BPF_ASSERT(cpu_info_fd >= 0); | 782 BPF_ASSERT(cpu_info_fd >= 0); |
784 char buf[1024]; | 783 char buf[1024]; |
785 BPF_ASSERT(read(cpu_info_fd, buf, sizeof(buf)) > 0); | 784 BPF_ASSERT(read(cpu_info_fd, buf, sizeof(buf)) > 0); |
786 } | 785 } |
787 | 786 |
788 // Simple test demonstrating how to use Sandbox::Cond() | 787 // Simple test demonstrating how to use SandboxBPF::Cond() |
789 | 788 |
790 ErrorCode SimpleCondTestPolicy(Sandbox* sandbox, int sysno, void*) { | 789 ErrorCode SimpleCondTestPolicy(SandboxBPF* sandbox, int sysno, void*) { |
791 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 790 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
792 // FIXME: we should really not have to do that in a trivial policy | 791 // FIXME: we should really not have to do that in a trivial policy |
793 return ErrorCode(ENOSYS); | 792 return ErrorCode(ENOSYS); |
794 } | 793 } |
795 | 794 |
796 // We deliberately return unusual errno values upon failure, so that we | 795 // We deliberately return unusual errno values upon failure, so that we |
797 // can uniquely test for these values. In a "real" policy, you would want | 796 // can uniquely test for these values. In a "real" policy, you would want |
798 // to return more traditional values. | 797 // to return more traditional values. |
799 switch (sysno) { | 798 switch (sysno) { |
800 case __NR_open: | 799 case __NR_open: |
801 // Allow opening files for reading, but don't allow writing. | 800 // Allow opening files for reading, but don't allow writing. |
(...skipping 30 matching lines...) Expand all Loading... | |
832 BPF_ASSERT((fd = open("/proc/self/comm", O_RDONLY)) >= 0); | 831 BPF_ASSERT((fd = open("/proc/self/comm", O_RDONLY)) >= 0); |
833 close(fd); | 832 close(fd); |
834 | 833 |
835 int ret; | 834 int ret; |
836 BPF_ASSERT((ret = prctl(PR_GET_DUMPABLE)) >= 0); | 835 BPF_ASSERT((ret = prctl(PR_GET_DUMPABLE)) >= 0); |
837 BPF_ASSERT(prctl(PR_SET_DUMPABLE, 1 - ret) == 0); | 836 BPF_ASSERT(prctl(PR_SET_DUMPABLE, 1 - ret) == 0); |
838 BPF_ASSERT(prctl(PR_GET_ENDIAN, &ret) == -1); | 837 BPF_ASSERT(prctl(PR_GET_ENDIAN, &ret) == -1); |
839 BPF_ASSERT(errno == ENOMEM); | 838 BPF_ASSERT(errno == ENOMEM); |
840 } | 839 } |
841 | 840 |
842 // This test exercises the Sandbox::Cond() method by building a complex | 841 // This test exercises the SandboxBPF::Cond() method by building a complex |
843 // tree of conditional equality operations. It then makes system calls and | 842 // tree of conditional equality operations. It then makes system calls and |
844 // verifies that they return the values that we expected from our BPF | 843 // verifies that they return the values that we expected from our BPF |
845 // program. | 844 // program. |
846 class EqualityStressTest { | 845 class EqualityStressTest { |
847 public: | 846 public: |
848 EqualityStressTest() { | 847 EqualityStressTest() { |
849 // We want a deterministic test | 848 // We want a deterministic test |
850 srand(0); | 849 srand(0); |
851 | 850 |
852 // Iterates over system call numbers and builds a random tree of | 851 // Iterates over system call numbers and builds a random tree of |
(...skipping 19 matching lines...) Expand all Loading... | |
872 } | 871 } |
873 | 872 |
874 ~EqualityStressTest() { | 873 ~EqualityStressTest() { |
875 for (std::vector<ArgValue*>::iterator iter = arg_values_.begin(); | 874 for (std::vector<ArgValue*>::iterator iter = arg_values_.begin(); |
876 iter != arg_values_.end(); | 875 iter != arg_values_.end(); |
877 ++iter) { | 876 ++iter) { |
878 DeleteArgValue(*iter); | 877 DeleteArgValue(*iter); |
879 } | 878 } |
880 } | 879 } |
881 | 880 |
882 ErrorCode Policy(Sandbox* sandbox, int sysno) { | 881 ErrorCode Policy(SandboxBPF* sandbox, int sysno) { |
883 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 882 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
884 // FIXME: we should really not have to do that in a trivial policy | 883 // FIXME: we should really not have to do that in a trivial policy |
885 return ErrorCode(ENOSYS); | 884 return ErrorCode(ENOSYS); |
886 } else if (sysno < 0 || sysno >= (int)arg_values_.size() || | 885 } else if (sysno < 0 || sysno >= (int)arg_values_.size() || |
887 IsReservedSyscall(sysno)) { | 886 IsReservedSyscall(sysno)) { |
888 // We only return ErrorCode values for the system calls that | 887 // We only return ErrorCode values for the system calls that |
889 // are part of our test data. Every other system call remains | 888 // are part of our test data. Every other system call remains |
890 // allowed. | 889 // allowed. |
891 return ErrorCode(ErrorCode::ERR_ALLOWED); | 890 return ErrorCode(ErrorCode::ERR_ALLOWED); |
892 } else { | 891 } else { |
893 // ToErrorCode() turns an ArgValue object into an ErrorCode that is | 892 // ToErrorCode() turns an ArgValue object into an ErrorCode that is |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1032 } | 1031 } |
1033 delete[] arg_value->tests; | 1032 delete[] arg_value->tests; |
1034 } | 1033 } |
1035 if (!arg_value->err) { | 1034 if (!arg_value->err) { |
1036 DeleteArgValue(arg_value->arg_value); | 1035 DeleteArgValue(arg_value->arg_value); |
1037 } | 1036 } |
1038 delete arg_value; | 1037 delete arg_value; |
1039 } | 1038 } |
1040 } | 1039 } |
1041 | 1040 |
1042 ErrorCode ToErrorCode(Sandbox* sandbox, ArgValue* arg_value) { | 1041 ErrorCode ToErrorCode(SandboxBPF* sandbox, ArgValue* arg_value) { |
1043 // Compute the ErrorCode that should be returned, if none of our | 1042 // Compute the ErrorCode that should be returned, if none of our |
1044 // tests succeed (i.e. the system call parameter doesn't match any | 1043 // tests succeed (i.e. the system call parameter doesn't match any |
1045 // of the values in arg_value->tests[].k_value). | 1044 // of the values in arg_value->tests[].k_value). |
1046 ErrorCode err; | 1045 ErrorCode err; |
1047 if (arg_value->err) { | 1046 if (arg_value->err) { |
1048 // If this was a leaf node, return the errno value that we expect to | 1047 // If this was a leaf node, return the errno value that we expect to |
1049 // return from the BPF filter program. | 1048 // return from the BPF filter program. |
1050 err = ErrorCode(arg_value->err); | 1049 err = ErrorCode(arg_value->err); |
1051 } else { | 1050 } else { |
1052 // If this wasn't a leaf node yet, recursively descend into the rest | 1051 // If this wasn't a leaf node yet, recursively descend into the rest |
1053 // of the tree. This will end up adding a few more Sandbox::Cond() | 1052 // of the tree. This will end up adding a few more SandboxBPF::Cond() |
1054 // tests to our ErrorCode. | 1053 // tests to our ErrorCode. |
1055 err = ToErrorCode(sandbox, arg_value->arg_value); | 1054 err = ToErrorCode(sandbox, arg_value->arg_value); |
1056 } | 1055 } |
1057 | 1056 |
1058 // Now, iterate over all the test cases that we want to compare against. | 1057 // Now, iterate over all the test cases that we want to compare against. |
1059 // This builds a chain of Sandbox::Cond() tests | 1058 // This builds a chain of SandboxBPF::Cond() tests |
1060 // (aka "if ... elif ... elif ... elif ... fi") | 1059 // (aka "if ... elif ... elif ... elif ... fi") |
1061 for (int n = arg_value->size; n-- > 0;) { | 1060 for (int n = arg_value->size; n-- > 0;) { |
1062 ErrorCode matched; | 1061 ErrorCode matched; |
1063 // Again, we distinguish between leaf nodes and subtrees. | 1062 // Again, we distinguish between leaf nodes and subtrees. |
1064 if (arg_value->tests[n].err) { | 1063 if (arg_value->tests[n].err) { |
1065 matched = ErrorCode(arg_value->tests[n].err); | 1064 matched = ErrorCode(arg_value->tests[n].err); |
1066 } else { | 1065 } else { |
1067 matched = ToErrorCode(sandbox, arg_value->tests[n].arg_value); | 1066 matched = ToErrorCode(sandbox, arg_value->tests[n].arg_value); |
1068 } | 1067 } |
1069 // For now, all of our tests are limited to 32bit. | 1068 // For now, all of our tests are limited to 32bit. |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1133 std::vector<ArgValue*> arg_values_; | 1132 std::vector<ArgValue*> arg_values_; |
1134 | 1133 |
1135 // Don't increase these values. We are pushing the limits of the maximum | 1134 // Don't increase these values. We are pushing the limits of the maximum |
1136 // BPF program that the kernel will allow us to load. If the values are | 1135 // BPF program that the kernel will allow us to load. If the values are |
1137 // increased too much, the test will start failing. | 1136 // increased too much, the test will start failing. |
1138 static const int kNumTestCases = 40; | 1137 static const int kNumTestCases = 40; |
1139 static const int kMaxFanOut = 3; | 1138 static const int kMaxFanOut = 3; |
1140 static const int kMaxArgs = 6; | 1139 static const int kMaxArgs = 6; |
1141 }; | 1140 }; |
1142 | 1141 |
1143 ErrorCode EqualityStressTestPolicy(Sandbox* sandbox, int sysno, void* aux) { | 1142 ErrorCode EqualityStressTestPolicy(SandboxBPF* sandbox, int sysno, void* aux) { |
1144 return reinterpret_cast<EqualityStressTest*>(aux)->Policy(sandbox, sysno); | 1143 return reinterpret_cast<EqualityStressTest*>(aux)->Policy(sandbox, sysno); |
1145 } | 1144 } |
1146 | 1145 |
1147 BPF_TEST(SandboxBpf, | 1146 BPF_TEST(SandboxBpf, |
1148 EqualityTests, | 1147 EqualityTests, |
1149 EqualityStressTestPolicy, | 1148 EqualityStressTestPolicy, |
1150 EqualityStressTest /* BPF_AUX */) { | 1149 EqualityStressTest /* BPF_AUX */) { |
1151 BPF_AUX.VerifyFilter(); | 1150 BPF_AUX.VerifyFilter(); |
1152 } | 1151 } |
1153 | 1152 |
1154 ErrorCode EqualityArgumentWidthPolicy(Sandbox* sandbox, int sysno, void*) { | 1153 ErrorCode EqualityArgumentWidthPolicy(SandboxBPF* sandbox, int sysno, void*) { |
1155 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 1154 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
1156 // FIXME: we should really not have to do that in a trivial policy | 1155 // FIXME: we should really not have to do that in a trivial policy |
1157 return ErrorCode(ENOSYS); | 1156 return ErrorCode(ENOSYS); |
1158 } else if (sysno == __NR_uname) { | 1157 } else if (sysno == __NR_uname) { |
1159 return sandbox->Cond( | 1158 return sandbox->Cond( |
1160 0, | 1159 0, |
1161 ErrorCode::TP_32BIT, | 1160 ErrorCode::TP_32BIT, |
1162 ErrorCode::OP_EQUAL, | 1161 ErrorCode::OP_EQUAL, |
1163 0, | 1162 0, |
1164 sandbox->Cond(1, | 1163 sandbox->Cond(1, |
1165 ErrorCode::TP_32BIT, | 1164 ErrorCode::TP_32BIT, |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1207 // syscall interface. So, we have to skip the part of the test that requires | 1206 // syscall interface. So, we have to skip the part of the test that requires |
1208 // 64bit arguments. | 1207 // 64bit arguments. |
1209 BPF_DEATH_TEST(SandboxBpf, | 1208 BPF_DEATH_TEST(SandboxBpf, |
1210 EqualityArgumentUnallowed64bit, | 1209 EqualityArgumentUnallowed64bit, |
1211 DEATH_MESSAGE("Unexpected 64bit argument detected"), | 1210 DEATH_MESSAGE("Unexpected 64bit argument detected"), |
1212 EqualityArgumentWidthPolicy) { | 1211 EqualityArgumentWidthPolicy) { |
1213 SandboxSyscall(__NR_uname, 0, 0x5555555555555555ULL); | 1212 SandboxSyscall(__NR_uname, 0, 0x5555555555555555ULL); |
1214 } | 1213 } |
1215 #endif | 1214 #endif |
1216 | 1215 |
1217 ErrorCode EqualityWithNegativeArgumentsPolicy(Sandbox* sandbox, | 1216 ErrorCode EqualityWithNegativeArgumentsPolicy(SandboxBPF* sandbox, |
1218 int sysno, | 1217 int sysno, |
1219 void*) { | 1218 void*) { |
1220 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 1219 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
1221 // FIXME: we should really not have to do that in a trivial policy | 1220 // FIXME: we should really not have to do that in a trivial policy |
1222 return ErrorCode(ENOSYS); | 1221 return ErrorCode(ENOSYS); |
1223 } else if (sysno == __NR_uname) { | 1222 } else if (sysno == __NR_uname) { |
1224 return sandbox->Cond(0, | 1223 return sandbox->Cond(0, |
1225 ErrorCode::TP_32BIT, | 1224 ErrorCode::TP_32BIT, |
1226 ErrorCode::OP_EQUAL, | 1225 ErrorCode::OP_EQUAL, |
1227 0xFFFFFFFF, | 1226 0xFFFFFFFF, |
1228 ErrorCode(1), | 1227 ErrorCode(1), |
1229 ErrorCode(2)); | 1228 ErrorCode(2)); |
1230 } else { | 1229 } else { |
(...skipping 13 matching lines...) Expand all Loading... | |
1244 BPF_DEATH_TEST(SandboxBpf, | 1243 BPF_DEATH_TEST(SandboxBpf, |
1245 EqualityWithNegative64bitArguments, | 1244 EqualityWithNegative64bitArguments, |
1246 DEATH_MESSAGE("Unexpected 64bit argument detected"), | 1245 DEATH_MESSAGE("Unexpected 64bit argument detected"), |
1247 EqualityWithNegativeArgumentsPolicy) { | 1246 EqualityWithNegativeArgumentsPolicy) { |
1248 // When expecting a 32bit system call argument, we look at the MSB of the | 1247 // When expecting a 32bit system call argument, we look at the MSB of the |
1249 // 64bit value and allow both "0" and "-1". But the latter is allowed only | 1248 // 64bit value and allow both "0" and "-1". But the latter is allowed only |
1250 // iff the LSB was negative. So, this death test should error out. | 1249 // iff the LSB was negative. So, this death test should error out. |
1251 BPF_ASSERT(SandboxSyscall(__NR_uname, 0xFFFFFFFF00000000LL) == -1); | 1250 BPF_ASSERT(SandboxSyscall(__NR_uname, 0xFFFFFFFF00000000LL) == -1); |
1252 } | 1251 } |
1253 #endif | 1252 #endif |
1254 ErrorCode AllBitTestPolicy(Sandbox *sandbox, int sysno, void *) { | 1253 ErrorCode AllBitTestPolicy(SandboxBPF* sandbox, int sysno, void *) { |
1255 // Test the OP_HAS_ALL_BITS conditional test operator with a couple of | 1254 // Test the OP_HAS_ALL_BITS conditional test operator with a couple of |
1256 // different bitmasks. We try to find bitmasks that could conceivably | 1255 // different bitmasks. We try to find bitmasks that could conceivably |
1257 // touch corner cases. | 1256 // touch corner cases. |
1258 // For all of these tests, we override the uname(). We can make use with | 1257 // For all of these tests, we override the uname(). We can make use with |
1259 // a single system call number, as we use the first system call argument to | 1258 // a single system call number, as we use the first system call argument to |
1260 // select the different bit masks that we want to test against. | 1259 // select the different bit masks that we want to test against. |
1261 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 1260 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
1262 // FIXME: we should really not have to do that in a trivial policy | 1261 // FIXME: we should really not have to do that in a trivial policy |
1263 return ErrorCode(ENOSYS); | 1262 return ErrorCode(ENOSYS); |
1264 } else if (sysno == __NR_uname) { | 1263 } else if (sysno == __NR_uname) { |
1265 return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 0, | 1264 return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 0, |
1266 sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ALL_BITS, | 1265 sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ALL_BITS, |
1267 0x0, | 1266 0x0, |
1268 ErrorCode(1), ErrorCode(0)), | 1267 ErrorCode(1), ErrorCode(0)), |
1269 | 1268 |
1270 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 1, | 1269 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 1, |
1271 sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ALL_BITS, | 1270 sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ALL_BITS, |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1440 | 1439 |
1441 // 64bit test: all of 0x100000001 | 1440 // 64bit test: all of 0x100000001 |
1442 BITMASK_TEST(10, 0x000000000LL, ALLBITS64,0x100000001, EXPECT_FAILURE); | 1441 BITMASK_TEST(10, 0x000000000LL, ALLBITS64,0x100000001, EXPECT_FAILURE); |
1443 BITMASK_TEST(10, 0x000000001LL, ALLBITS64,0x100000001, EXPECT_FAILURE); | 1442 BITMASK_TEST(10, 0x000000001LL, ALLBITS64,0x100000001, EXPECT_FAILURE); |
1444 BITMASK_TEST(10, 0x100000000LL, ALLBITS64,0x100000001, EXPECT_FAILURE); | 1443 BITMASK_TEST(10, 0x100000000LL, ALLBITS64,0x100000001, EXPECT_FAILURE); |
1445 BITMASK_TEST(10, 0x100000001LL, ALLBITS64,0x100000001, EXPT64_SUCCESS); | 1444 BITMASK_TEST(10, 0x100000001LL, ALLBITS64,0x100000001, EXPT64_SUCCESS); |
1446 BITMASK_TEST(10, 0xFFFFFFFFU, ALLBITS64,0x100000001, EXPECT_FAILURE); | 1445 BITMASK_TEST(10, 0xFFFFFFFFU, ALLBITS64,0x100000001, EXPECT_FAILURE); |
1447 BITMASK_TEST(10, -1L, ALLBITS64,0x100000001, EXPT64_SUCCESS); | 1446 BITMASK_TEST(10, -1L, ALLBITS64,0x100000001, EXPT64_SUCCESS); |
1448 } | 1447 } |
1449 | 1448 |
1450 ErrorCode AnyBitTestPolicy(Sandbox* sandbox, int sysno, void*) { | 1449 ErrorCode AnyBitTestPolicy(SandboxBPF* sandbox, int sysno, void*) { |
1451 // Test the OP_HAS_ANY_BITS conditional test operator with a couple of | 1450 // Test the OP_HAS_ANY_BITS conditional test operator with a couple of |
1452 // different bitmasks. We try to find bitmasks that could conceivably | 1451 // different bitmasks. We try to find bitmasks that could conceivably |
1453 // touch corner cases. | 1452 // touch corner cases. |
1454 // For all of these tests, we override the uname(). We can make use with | 1453 // For all of these tests, we override the uname(). We can make use with |
1455 // a single system call number, as we use the first system call argument to | 1454 // a single system call number, as we use the first system call argument to |
1456 // select the different bit masks that we want to test against. | 1455 // select the different bit masks that we want to test against. |
1457 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 1456 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
1458 // FIXME: we should really not have to do that in a trivial policy | 1457 // FIXME: we should really not have to do that in a trivial policy |
1459 return ErrorCode(ENOSYS); | 1458 return ErrorCode(ENOSYS); |
1460 } else if (sysno == __NR_uname) { | 1459 } else if (sysno == __NR_uname) { |
1461 return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 0, | 1460 return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 0, |
1462 sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, | 1461 sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, |
1463 0x0, | 1462 0x0, |
1464 ErrorCode(1), ErrorCode(0)), | 1463 ErrorCode(1), ErrorCode(0)), |
1465 | 1464 |
1466 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 1, | 1465 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 1, |
1467 sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, | 1466 sandbox->Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1644 (long long)args.args[0], | 1643 (long long)args.args[0], |
1645 (long long)args.args[1], | 1644 (long long)args.args[1], |
1646 (long long)args.args[2], | 1645 (long long)args.args[2], |
1647 (long long)args.args[3], | 1646 (long long)args.args[3], |
1648 (long long)args.args[4], | 1647 (long long)args.args[4], |
1649 (long long)args.args[5], | 1648 (long long)args.args[5], |
1650 msg); | 1649 msg); |
1651 } | 1650 } |
1652 return -EPERM; | 1651 return -EPERM; |
1653 } | 1652 } |
1654 ErrorCode PthreadPolicyEquality(Sandbox* sandbox, int sysno, void* aux) { | 1653 ErrorCode PthreadPolicyEquality(SandboxBPF* sandbox, int sysno, void* aux) { |
1655 // This policy allows creating threads with pthread_create(). But it | 1654 // This policy allows creating threads with pthread_create(). But it |
1656 // doesn't allow any other uses of clone(). Most notably, it does not | 1655 // doesn't allow any other uses of clone(). Most notably, it does not |
1657 // allow callers to implement fork() or vfork() by passing suitable flags | 1656 // allow callers to implement fork() or vfork() by passing suitable flags |
1658 // to the clone() system call. | 1657 // to the clone() system call. |
1659 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 1658 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
1660 // FIXME: we should really not have to do that in a trivial policy | 1659 // FIXME: we should really not have to do that in a trivial policy |
1661 return ErrorCode(ENOSYS); | 1660 return ErrorCode(ENOSYS); |
1662 } else if (sysno == __NR_clone) { | 1661 } else if (sysno == __NR_clone) { |
1663 // We have seen two different valid combinations of flags. Glibc | 1662 // We have seen two different valid combinations of flags. Glibc |
1664 // uses the more modern flags, sets the TLS from the call to clone(), and | 1663 // uses the more modern flags, sets the TLS from the call to clone(), and |
1665 // uses futexes to monitor threads. Android's C run-time library, doesn't | 1664 // uses futexes to monitor threads. Android's C run-time library, doesn't |
1666 // do any of this, but it sets the obsolete (and no-op) CLONE_DETACHED. | 1665 // do any of this, but it sets the obsolete (and no-op) CLONE_DETACHED. |
1667 // More recent versions of Android don't set CLONE_DETACHED anymore, so | 1666 // More recent versions of Android don't set CLONE_DETACHED anymore, so |
1668 // the last case accounts for that. | 1667 // the last case accounts for that. |
1669 // The following policy is very strict. It only allows the exact masks | 1668 // The following policy is very strict. It only allows the exact masks |
(...skipping 14 matching lines...) Expand all Loading... | |
1684 ErrorCode(ErrorCode::ERR_ALLOWED), | 1683 ErrorCode(ErrorCode::ERR_ALLOWED), |
1685 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, | 1684 sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, |
1686 kBaseAndroidCloneMask, | 1685 kBaseAndroidCloneMask, |
1687 ErrorCode(ErrorCode::ERR_ALLOWED), | 1686 ErrorCode(ErrorCode::ERR_ALLOWED), |
1688 sandbox->Trap(PthreadTrapHandler, "Unknown mask")))); | 1687 sandbox->Trap(PthreadTrapHandler, "Unknown mask")))); |
1689 } else { | 1688 } else { |
1690 return ErrorCode(ErrorCode::ERR_ALLOWED); | 1689 return ErrorCode(ErrorCode::ERR_ALLOWED); |
1691 } | 1690 } |
1692 } | 1691 } |
1693 | 1692 |
1694 ErrorCode PthreadPolicyBitMask(Sandbox* sandbox, int sysno, void* aux) { | 1693 ErrorCode PthreadPolicyBitMask(SandboxBPF* sandbox, int sysno, void* aux) { |
1695 // This policy allows creating threads with pthread_create(). But it | 1694 // This policy allows creating threads with pthread_create(). But it |
1696 // doesn't allow any other uses of clone(). Most notably, it does not | 1695 // doesn't allow any other uses of clone(). Most notably, it does not |
1697 // allow callers to implement fork() or vfork() by passing suitable flags | 1696 // allow callers to implement fork() or vfork() by passing suitable flags |
1698 // to the clone() system call. | 1697 // to the clone() system call. |
1699 if (!Sandbox::IsValidSyscallNumber(sysno)) { | 1698 if (!SandboxBPF::IsValidSyscallNumber(sysno)) { |
1700 // FIXME: we should really not have to do that in a trivial policy | 1699 // FIXME: we should really not have to do that in a trivial policy |
1701 return ErrorCode(ENOSYS); | 1700 return ErrorCode(ENOSYS); |
1702 } else if (sysno == __NR_clone) { | 1701 } else if (sysno == __NR_clone) { |
1703 // We have seen two different valid combinations of flags. Glibc | 1702 // We have seen two different valid combinations of flags. Glibc |
1704 // uses the more modern flags, sets the TLS from the call to clone(), and | 1703 // uses the more modern flags, sets the TLS from the call to clone(), and |
1705 // uses futexes to monitor threads. Android's C run-time library, doesn't | 1704 // uses futexes to monitor threads. Android's C run-time library, doesn't |
1706 // do any of this, but it sets the obsolete (and no-op) CLONE_DETACHED. | 1705 // do any of this, but it sets the obsolete (and no-op) CLONE_DETACHED. |
1707 // The following policy allows for either combination of flags, but it | 1706 // The following policy allows for either combination of flags, but it |
1708 // is generally a little more conservative than strictly necessary. We | 1707 // is generally a little more conservative than strictly necessary. We |
1709 // err on the side of rather safe than sorry. | 1708 // err on the side of rather safe than sorry. |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1772 CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | SIGCHLD, | 1771 CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | SIGCHLD, |
1773 0, | 1772 0, |
1774 0, | 1773 0, |
1775 &pid) == -EPERM); | 1774 &pid) == -EPERM); |
1776 } | 1775 } |
1777 | 1776 |
1778 BPF_TEST(SandboxBpf, PthreadEquality, PthreadPolicyEquality) { PthreadTest(); } | 1777 BPF_TEST(SandboxBpf, PthreadEquality, PthreadPolicyEquality) { PthreadTest(); } |
1779 | 1778 |
1780 BPF_TEST(SandboxBpf, PthreadBitMask, PthreadPolicyBitMask) { PthreadTest(); } | 1779 BPF_TEST(SandboxBpf, PthreadBitMask, PthreadPolicyBitMask) { PthreadTest(); } |
1781 | 1780 |
1782 } // namespace | 1781 } // namespace. |
Robert Sesek
2013/12/10 15:07:46
nit: no period
jln (very slow on Chromium)
2013/12/10 18:43:47
Done.
| |
1782 | |
1783 } // namespace sandbox. | |
OLD | NEW |