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

Side by Side Diff: sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc

Issue 11363212: Added support for greylisting of system calls. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Now with more meat Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <ostream> 5 #include <ostream>
6 6
7 #include "sandbox/linux/seccomp-bpf/bpf_tests.h" 7 #include "sandbox/linux/seccomp-bpf/bpf_tests.h"
8 #include "sandbox/linux/seccomp-bpf/syscall.h"
8 #include "sandbox/linux/seccomp-bpf/verifier.h" 9 #include "sandbox/linux/seccomp-bpf/verifier.h"
9 #include "testing/gtest/include/gtest/gtest.h" 10 #include "testing/gtest/include/gtest/gtest.h"
10 11
11 using namespace playground2; 12 using namespace playground2;
12 13
13 namespace { 14 namespace {
14 15
15 const int kExpectedReturnValue = 42; 16 const int kExpectedReturnValue = 42;
16 17
17 // This test should execute no matter whether we have kernel support. So, 18 // This test should execute no matter whether we have kernel support. So,
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 for (int syscall_number = static_cast<int>(__ARM_NR_set_tls + 1); 258 for (int syscall_number = static_cast<int>(__ARM_NR_set_tls + 1);
258 syscall_number <= static_cast<int>(MAX_PRIVATE_SYSCALL); 259 syscall_number <= static_cast<int>(MAX_PRIVATE_SYSCALL);
259 ++syscall_number) { 260 ++syscall_number) {
260 errno = 0; 261 errno = 0;
261 BPF_ASSERT(syscall(syscall_number) == -1); 262 BPF_ASSERT(syscall(syscall_number) == -1);
262 BPF_ASSERT(errno == ArmPrivateSysnoToErrno(syscall_number)); 263 BPF_ASSERT(errno == ArmPrivateSysnoToErrno(syscall_number));
263 } 264 }
264 } 265 }
265 #endif // defined(__arm__) 266 #endif // defined(__arm__)
266 267
268 TEST(SandboxBpf, Syscall) {
269 // Test that we can do basic system calls
270 EXPECT_EQ(Syscall(__NR_getpid), syscall(__NR_getpid));
271
272 // Test that Syscall(-1) is handled specially
273 EXPECT_NE(Syscall(-1), syscall(-1));
274
275 // If possible, test that Syscall(-1) returns the address right after a
276 // kernel entry point.
277 #if defined(__i386__)
278 EXPECT_EQ(((uint16_t *)Syscall(-1))[-1], 0x80CDu); // INT 0x80
279 #elif defined(__x86_64__)
280 EXPECT_EQ(((uint16_t *)Syscall(-1))[-1], 0x050Fu); // SYSCALL
281 #elif defined(__arm__)
282 #if defined(__thumb__)
283 EXPECT_EQ(((uint16_t *)Syscall(-1))[-1], 0xDF00u); // SWI 0
284 #else
285 EXPECT_EQ(((uint32_t *)Syscall(-1))[-1], 0xEF000000u); // SVC 0
286 #endif
287 #else
288 #warning Incomplete test case; need port for target platform
289 #endif
290 }
291
292 intptr_t CountSyscalls(const struct arch_seccomp_data& args, void *aux) {
293 // Count all invocations of our callback function.
294 ++*reinterpret_cast<int *>(aux);
295
296 // Verify that within the callback function all filtering is temporarily
297 // disabled.
298 BPF_ASSERT(syscall(__NR_getpid) > 1);
299
300 // Verify that we can now call the underlying system call without causing
301 // infinite recursion.
302 return (intptr_t)(syscall(args.nr, args.args[0], args.args[1],
303 args.args[2], args.args[3],
304 args.args[4], args.args[5]));
305 }
306
307 ErrorCode GreyListedPolicy(int sysno, void *aux) {
308 // The use of UnsafeTrap() causes us to print a warning message. This is
309 // generally desirable, but it results in the unittest failing, as it doesn't
310 // expect any messages on "stderr". So, temporarily disable messages. The
311 // BPF_TEST() is guaranteed to turn messages back on, after the policy
312 // function has completed.
313 Die::SuppressInfoMessages(true);
314
315 // Some system calls must always be allowed, if our policy wants to make
316 // use of UnsafeTrap()
317 if (sysno == __NR_rt_sigprocmask ||
318 sysno == __NR_rt_sigreturn
319 #if defined(__NR_sigprocmask)
320 || sysno == __NR_sigprocmask
321 #endif
322 #if defined(__NR_sigreturn)
323 || sysno == __NR_sigreturn
324 #endif
325 ) {
326 return ErrorCode(ErrorCode::ERR_ALLOWED);
327 } else if (sysno == __NR_getpid) {
328 // Disallow getpid()
329 return ErrorCode(EPERM);
330 } else if (Sandbox::isValidSyscallNumber(sysno)) {
331 // Allow (and count) all other system calls.
332 return Sandbox::UnsafeTrap(CountSyscalls, aux);
333 } else {
334 return ErrorCode(ENOSYS);
335 }
336 }
337
338 BPF_TEST(SandboxBpf, GreyListedPolicy,
339 GreyListedPolicy, int /* BPF_AUX */) {
340 BPF_ASSERT(syscall(__NR_getpid) == -1);
341 BPF_ASSERT(errno == EPERM);
342 BPF_ASSERT(BPF_AUX == 0);
343 BPF_ASSERT(syscall(__NR_geteuid) == syscall(__NR_getuid));
344 BPF_ASSERT(BPF_AUX == 2);
345 }
346
347 intptr_t AllowRedirectedSyscall(const struct arch_seccomp_data& args, void *) {
348 return (intptr_t)(syscall(args.nr,
349 (void *)args.args[0], (void *)args.args[1],
350 (void *)args.args[2], (void *)args.args[3],
351 (void *)args.args[4], (void *)args.args[5]));
352 }
353
354 ErrorCode RedirectAllSyscallsPolicy(int sysno, void *aux) {
355 Die::SuppressInfoMessages(true);
356
357 // Some system calls must always be allowed, if our policy wants to make
358 // use of UnsafeTrap()
359 if (sysno == __NR_rt_sigprocmask ||
360 sysno == __NR_rt_sigreturn
361 #if defined(__NR_sigprocmask)
362 || sysno == __NR_sigprocmask
363 #endif
364 #if defined(__NR_sigreturn)
365 || sysno == __NR_sigreturn
366 #endif
367 ) {
368 return ErrorCode(ErrorCode::ERR_ALLOWED);
369 } else if (Sandbox::isValidSyscallNumber(sysno)) {
370 return Sandbox::UnsafeTrap(AllowRedirectedSyscall, aux);
371 } else {
372 return ErrorCode(ENOSYS);
373 }
374 }
375
376 int bus_handler_fd_ = -1;
377
378 void SigBusHandler(int, siginfo_t *info, void *void_context) {
379 BPF_ASSERT(write(bus_handler_fd_, "\x55", 1) == 1);
380 }
381
382 BPF_TEST(SandboxBpf, SigBus, RedirectAllSyscallsPolicy) {
383 int fds[2];
384 BPF_ASSERT(pipe(fds) == 0);
385 bus_handler_fd_ = fds[1];
386 struct sigaction sa = { };
387 sa.sa_sigaction = SigBusHandler;
388 sa.sa_flags = SA_SIGINFO;
389 BPF_ASSERT(sigaction(SIGBUS, &sa, NULL) == 0);
390 raise(SIGBUS);
391 char c = '\000';
392 BPF_ASSERT(read(fds[0], &c, 1) == 1);
393 BPF_ASSERT(close(fds[0]) == 0);
394 BPF_ASSERT(close(fds[1]) == 0);
395 BPF_ASSERT(c == 0x55);
396 }
397
398 BPF_TEST(SandboxBpf, SigMask, RedirectAllSyscallsPolicy) {
399 sigset_t mask0, mask1, mask2;
400 sigemptyset(&mask0);
401 BPF_ASSERT(!sigprocmask(SIG_BLOCK, &mask0, &mask1));
402 BPF_ASSERT(!sigismember(&mask1, SIGUSR1));
403 sigaddset(&mask0, SIGUSR1);
404 BPF_ASSERT(!sigprocmask(SIG_BLOCK, &mask0, NULL));
405 BPF_ASSERT(!sigprocmask(SIG_BLOCK, &mask0, &mask2));
406 BPF_ASSERT( sigismember(&mask2, SIGUSR1));
407 }
408
267 } // namespace 409 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698