diff options
author | Robert Sesek <rsesek@google.com> | 2015-11-02 15:28:49 -0500 |
---|---|---|
committer | Shuah Khan <shuahkh@osg.samsung.com> | 2015-11-02 16:41:02 -0500 |
commit | fd88d16c58c2ad689a68d6790c789e7d5be3fc5b (patch) | |
tree | c5428d64cb4c8942cac53694828bf261f9b76f08 | |
parent | 256d0afb11d6e878e8c793e4a6e3bbfb81f9aae8 (diff) |
selftests/seccomp: Be more precise with syscall arguments.
Certain syscall emulation layers strictly check that the number of
arguments match what the syscall handler expects. The KILL_one_arg_one and
KILL_one_arg_six tests passed more parameters than expected to various
syscalls, causing failures in this emulation mode. Instead, test using
syscalls that take the appropriate number of arguments.
Signed-off-by: Robert Sesek <rsesek@google.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
-rw-r--r-- | tools/testing/selftests/seccomp/seccomp_bpf.c | 46 |
1 files changed, 35 insertions, 11 deletions
diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c index e7bc5d3533da..e38cc54942db 100644 --- a/tools/testing/selftests/seccomp/seccomp_bpf.c +++ b/tools/testing/selftests/seccomp/seccomp_bpf.c | |||
@@ -29,6 +29,9 @@ | |||
29 | #include <linux/elf.h> | 29 | #include <linux/elf.h> |
30 | #include <sys/uio.h> | 30 | #include <sys/uio.h> |
31 | #include <sys/utsname.h> | 31 | #include <sys/utsname.h> |
32 | #include <sys/fcntl.h> | ||
33 | #include <sys/mman.h> | ||
34 | #include <sys/times.h> | ||
32 | 35 | ||
33 | #define _GNU_SOURCE | 36 | #define _GNU_SOURCE |
34 | #include <unistd.h> | 37 | #include <unistd.h> |
@@ -429,14 +432,16 @@ TEST_SIGNAL(KILL_one, SIGSYS) | |||
429 | 432 | ||
430 | TEST_SIGNAL(KILL_one_arg_one, SIGSYS) | 433 | TEST_SIGNAL(KILL_one_arg_one, SIGSYS) |
431 | { | 434 | { |
435 | void *fatal_address; | ||
432 | struct sock_filter filter[] = { | 436 | struct sock_filter filter[] = { |
433 | BPF_STMT(BPF_LD|BPF_W|BPF_ABS, | 437 | BPF_STMT(BPF_LD|BPF_W|BPF_ABS, |
434 | offsetof(struct seccomp_data, nr)), | 438 | offsetof(struct seccomp_data, nr)), |
435 | BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0), | 439 | BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_times, 1, 0), |
436 | BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), | 440 | BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), |
437 | /* Only both with lower 32-bit for now. */ | 441 | /* Only both with lower 32-bit for now. */ |
438 | BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_arg(0)), | 442 | BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_arg(0)), |
439 | BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x0C0FFEE, 0, 1), | 443 | BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, |
444 | (unsigned long)&fatal_address, 0, 1), | ||
440 | BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL), | 445 | BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL), |
441 | BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), | 446 | BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), |
442 | }; | 447 | }; |
@@ -446,7 +451,8 @@ TEST_SIGNAL(KILL_one_arg_one, SIGSYS) | |||
446 | }; | 451 | }; |
447 | long ret; | 452 | long ret; |
448 | pid_t parent = getppid(); | 453 | pid_t parent = getppid(); |
449 | pid_t pid = getpid(); | 454 | struct tms timebuf; |
455 | clock_t clock = times(&timebuf); | ||
450 | 456 | ||
451 | ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); | 457 | ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); |
452 | ASSERT_EQ(0, ret); | 458 | ASSERT_EQ(0, ret); |
@@ -455,17 +461,22 @@ TEST_SIGNAL(KILL_one_arg_one, SIGSYS) | |||
455 | ASSERT_EQ(0, ret); | 461 | ASSERT_EQ(0, ret); |
456 | 462 | ||
457 | EXPECT_EQ(parent, syscall(__NR_getppid)); | 463 | EXPECT_EQ(parent, syscall(__NR_getppid)); |
458 | EXPECT_EQ(pid, syscall(__NR_getpid)); | 464 | EXPECT_LE(clock, syscall(__NR_times, &timebuf)); |
459 | /* getpid() should never return. */ | 465 | /* times() should never return. */ |
460 | EXPECT_EQ(0, syscall(__NR_getpid, 0x0C0FFEE)); | 466 | EXPECT_EQ(0, syscall(__NR_times, &fatal_address)); |
461 | } | 467 | } |
462 | 468 | ||
463 | TEST_SIGNAL(KILL_one_arg_six, SIGSYS) | 469 | TEST_SIGNAL(KILL_one_arg_six, SIGSYS) |
464 | { | 470 | { |
471 | #ifndef __NR_mmap2 | ||
472 | int sysno = __NR_mmap; | ||
473 | #else | ||
474 | int sysno = __NR_mmap2; | ||
475 | #endif | ||
465 | struct sock_filter filter[] = { | 476 | struct sock_filter filter[] = { |
466 | BPF_STMT(BPF_LD|BPF_W|BPF_ABS, | 477 | BPF_STMT(BPF_LD|BPF_W|BPF_ABS, |
467 | offsetof(struct seccomp_data, nr)), | 478 | offsetof(struct seccomp_data, nr)), |
468 | BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0), | 479 | BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, sysno, 1, 0), |
469 | BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), | 480 | BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), |
470 | /* Only both with lower 32-bit for now. */ | 481 | /* Only both with lower 32-bit for now. */ |
471 | BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_arg(5)), | 482 | BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_arg(5)), |
@@ -479,7 +490,8 @@ TEST_SIGNAL(KILL_one_arg_six, SIGSYS) | |||
479 | }; | 490 | }; |
480 | long ret; | 491 | long ret; |
481 | pid_t parent = getppid(); | 492 | pid_t parent = getppid(); |
482 | pid_t pid = getpid(); | 493 | int fd; |
494 | void *map1, *map2; | ||
483 | 495 | ||
484 | ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); | 496 | ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); |
485 | ASSERT_EQ(0, ret); | 497 | ASSERT_EQ(0, ret); |
@@ -487,10 +499,22 @@ TEST_SIGNAL(KILL_one_arg_six, SIGSYS) | |||
487 | ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog); | 499 | ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog); |
488 | ASSERT_EQ(0, ret); | 500 | ASSERT_EQ(0, ret); |
489 | 501 | ||
502 | fd = open("/dev/zero", O_RDONLY); | ||
503 | ASSERT_NE(-1, fd); | ||
504 | |||
490 | EXPECT_EQ(parent, syscall(__NR_getppid)); | 505 | EXPECT_EQ(parent, syscall(__NR_getppid)); |
491 | EXPECT_EQ(pid, syscall(__NR_getpid)); | 506 | map1 = (void *)syscall(sysno, |
492 | /* getpid() should never return. */ | 507 | NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, fd, PAGE_SIZE); |
493 | EXPECT_EQ(0, syscall(__NR_getpid, 1, 2, 3, 4, 5, 0x0C0FFEE)); | 508 | EXPECT_NE(MAP_FAILED, map1); |
509 | /* mmap2() should never return. */ | ||
510 | map2 = (void *)syscall(sysno, | ||
511 | NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, fd, 0x0C0FFEE); | ||
512 | EXPECT_EQ(MAP_FAILED, map2); | ||
513 | |||
514 | /* The test failed, so clean up the resources. */ | ||
515 | munmap(map1, PAGE_SIZE); | ||
516 | munmap(map2, PAGE_SIZE); | ||
517 | close(fd); | ||
494 | } | 518 | } |
495 | 519 | ||
496 | /* TODO(wad) add 64-bit versus 32-bit arg tests. */ | 520 | /* TODO(wad) add 64-bit versus 32-bit arg tests. */ |