Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Robert Sesek and committed by
Shuah Khan
fd88d16c 256d0afb

+35 -11
+35 -11
tools/testing/selftests/seccomp/seccomp_bpf.c
··· 29 29 #include <linux/elf.h> 30 30 #include <sys/uio.h> 31 31 #include <sys/utsname.h> 32 + #include <sys/fcntl.h> 33 + #include <sys/mman.h> 34 + #include <sys/times.h> 32 35 33 36 #define _GNU_SOURCE 34 37 #include <unistd.h> ··· 432 429 433 430 TEST_SIGNAL(KILL_one_arg_one, SIGSYS) 434 431 { 432 + void *fatal_address; 435 433 struct sock_filter filter[] = { 436 434 BPF_STMT(BPF_LD|BPF_W|BPF_ABS, 437 435 offsetof(struct seccomp_data, nr)), 438 - BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0), 436 + BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_times, 1, 0), 439 437 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), 440 438 /* Only both with lower 32-bit for now. */ 441 439 BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_arg(0)), 442 - BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x0C0FFEE, 0, 1), 440 + BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 441 + (unsigned long)&fatal_address, 0, 1), 443 442 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL), 444 443 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), 445 444 }; ··· 451 446 }; 452 447 long ret; 453 448 pid_t parent = getppid(); 454 - pid_t pid = getpid(); 449 + struct tms timebuf; 450 + clock_t clock = times(&timebuf); 455 451 456 452 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); 457 453 ASSERT_EQ(0, ret); ··· 461 455 ASSERT_EQ(0, ret); 462 456 463 457 EXPECT_EQ(parent, syscall(__NR_getppid)); 464 - EXPECT_EQ(pid, syscall(__NR_getpid)); 465 - /* getpid() should never return. */ 466 - EXPECT_EQ(0, syscall(__NR_getpid, 0x0C0FFEE)); 458 + EXPECT_LE(clock, syscall(__NR_times, &timebuf)); 459 + /* times() should never return. */ 460 + EXPECT_EQ(0, syscall(__NR_times, &fatal_address)); 467 461 } 468 462 469 463 TEST_SIGNAL(KILL_one_arg_six, SIGSYS) 470 464 { 465 + #ifndef __NR_mmap2 466 + int sysno = __NR_mmap; 467 + #else 468 + int sysno = __NR_mmap2; 469 + #endif 471 470 struct sock_filter filter[] = { 472 471 BPF_STMT(BPF_LD|BPF_W|BPF_ABS, 473 472 offsetof(struct seccomp_data, nr)), 474 - BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0), 473 + BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, sysno, 1, 0), 475 474 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), 476 475 /* Only both with lower 32-bit for now. */ 477 476 BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_arg(5)), ··· 490 479 }; 491 480 long ret; 492 481 pid_t parent = getppid(); 493 - pid_t pid = getpid(); 482 + int fd; 483 + void *map1, *map2; 494 484 495 485 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); 496 486 ASSERT_EQ(0, ret); ··· 499 487 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog); 500 488 ASSERT_EQ(0, ret); 501 489 490 + fd = open("/dev/zero", O_RDONLY); 491 + ASSERT_NE(-1, fd); 492 + 502 493 EXPECT_EQ(parent, syscall(__NR_getppid)); 503 - EXPECT_EQ(pid, syscall(__NR_getpid)); 504 - /* getpid() should never return. */ 505 - EXPECT_EQ(0, syscall(__NR_getpid, 1, 2, 3, 4, 5, 0x0C0FFEE)); 494 + map1 = (void *)syscall(sysno, 495 + NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, fd, PAGE_SIZE); 496 + EXPECT_NE(MAP_FAILED, map1); 497 + /* mmap2() should never return. */ 498 + map2 = (void *)syscall(sysno, 499 + NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, fd, 0x0C0FFEE); 500 + EXPECT_EQ(MAP_FAILED, map2); 501 + 502 + /* The test failed, so clean up the resources. */ 503 + munmap(map1, PAGE_SIZE); 504 + munmap(map2, PAGE_SIZE); 505 + close(fd); 506 506 } 507 507 508 508 /* TODO(wad) add 64-bit versus 32-bit arg tests. */