selftests/seccomp: Refactor to use fixture variants
authorKees Cook <keescook@chromium.org>
Sun, 5 Jul 2020 06:12:31 +0000 (23:12 -0700)
committerShuah Khan <skhan@linuxfoundation.org>
Fri, 17 Jul 2020 19:37:28 +0000 (13:37 -0600)
Now that the selftest harness has variants, use them to eliminate a
bunch of copy/paste duplication.

Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Will Drewry <wad@chromium.org>
Cc: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
Acked-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
tools/testing/selftests/seccomp/seccomp_bpf.c

index 8c1cc8033c09f71451523f2be784aa14cd23221d..0ade3b0f595a4f497627279d5ada120e3be531c7 100644 (file)
@@ -1470,6 +1470,7 @@ pid_t setup_trace_fixture(struct __test_metadata *_metadata,
 
        return tracer_pid;
 }
+
 void teardown_trace_fixture(struct __test_metadata *_metadata,
                            pid_t tracer)
 {
@@ -1750,7 +1751,7 @@ void change_syscall(struct __test_metadata *_metadata,
        EXPECT_EQ(0, ret);
 }
 
-void tracer_syscall(struct __test_metadata *_metadata, pid_t tracee,
+void tracer_seccomp(struct __test_metadata *_metadata, pid_t tracee,
                    int status, void *args)
 {
        int ret;
@@ -1827,6 +1828,24 @@ FIXTURE(TRACE_syscall) {
        pid_t tracer, mytid, mypid, parent;
 };
 
+FIXTURE_VARIANT(TRACE_syscall) {
+       /*
+        * All of the SECCOMP_RET_TRACE behaviors can be tested with either
+        * SECCOMP_RET_TRACE+PTRACE_CONT or plain ptrace()+PTRACE_SYSCALL.
+        * This indicates if we should use SECCOMP_RET_TRACE (false), or
+        * ptrace (true).
+        */
+       bool use_ptrace;
+};
+
+FIXTURE_VARIANT_ADD(TRACE_syscall, ptrace) {
+       .use_ptrace = true,
+};
+
+FIXTURE_VARIANT_ADD(TRACE_syscall, seccomp) {
+       .use_ptrace = false,
+};
+
 FIXTURE_SETUP(TRACE_syscall)
 {
        struct sock_filter filter[] = {
@@ -1842,12 +1861,11 @@ FIXTURE_SETUP(TRACE_syscall)
                BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1005),
                BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
        };
-
-       memset(&self->prog, 0, sizeof(self->prog));
-       self->prog.filter = malloc(sizeof(filter));
-       ASSERT_NE(NULL, self->prog.filter);
-       memcpy(self->prog.filter, filter, sizeof(filter));
-       self->prog.len = (unsigned short)ARRAY_SIZE(filter);
+       struct sock_fprog prog = {
+               .len = (unsigned short)ARRAY_SIZE(filter),
+               .filter = filter,
+       };
+       long ret;
 
        /* Prepare some testable syscall results. */
        self->mytid = syscall(__NR_gettid);
@@ -1865,60 +1883,28 @@ FIXTURE_SETUP(TRACE_syscall)
        ASSERT_NE(self->parent, self->mypid);
 
        /* Launch tracer. */
-       self->tracer = setup_trace_fixture(_metadata, tracer_syscall, NULL,
-                                          false);
-}
-
-FIXTURE_TEARDOWN(TRACE_syscall)
-{
-       teardown_trace_fixture(_metadata, self->tracer);
-       if (self->prog.filter)
-               free(self->prog.filter);
-}
+       self->tracer = setup_trace_fixture(_metadata,
+                                          variant->use_ptrace ? tracer_ptrace
+                                                              : tracer_seccomp,
+                                          NULL, variant->use_ptrace);
 
-TEST_F(TRACE_syscall, ptrace_syscall_redirected)
-{
-       /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
-       teardown_trace_fixture(_metadata, self->tracer);
-       self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
-                                          true);
-
-       /* Tracer will redirect getpid to getppid. */
-       EXPECT_NE(self->mypid, syscall(__NR_getpid));
-}
+       ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+       ASSERT_EQ(0, ret);
 
-TEST_F(TRACE_syscall, ptrace_syscall_errno)
-{
-       /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
-       teardown_trace_fixture(_metadata, self->tracer);
-       self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
-                                          true);
+       if (variant->use_ptrace)
+               return;
 
-       /* Tracer should skip the open syscall, resulting in ESRCH. */
-       EXPECT_SYSCALL_RETURN(-ESRCH, syscall(__NR_openat));
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
+       ASSERT_EQ(0, ret);
 }
 
-TEST_F(TRACE_syscall, ptrace_syscall_faked)
+FIXTURE_TEARDOWN(TRACE_syscall)
 {
-       /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
        teardown_trace_fixture(_metadata, self->tracer);
-       self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
-                                          true);
-
-       /* Tracer should skip the gettid syscall, resulting fake pid. */
-       EXPECT_SYSCALL_RETURN(45000, syscall(__NR_gettid));
 }
 
 TEST_F(TRACE_syscall, syscall_allowed)
 {
-       long ret;
-
-       ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-       ASSERT_EQ(0, ret);
-
-       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
-       ASSERT_EQ(0, ret);
-
        /* getppid works as expected (no changes). */
        EXPECT_EQ(self->parent, syscall(__NR_getppid));
        EXPECT_NE(self->mypid, syscall(__NR_getppid));
@@ -1926,14 +1912,6 @@ TEST_F(TRACE_syscall, syscall_allowed)
 
 TEST_F(TRACE_syscall, syscall_redirected)
 {
-       long ret;
-
-       ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-       ASSERT_EQ(0, ret);
-
-       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
-       ASSERT_EQ(0, ret);
-
        /* getpid has been redirected to getppid as expected. */
        EXPECT_EQ(self->parent, syscall(__NR_getpid));
        EXPECT_NE(self->mypid, syscall(__NR_getpid));
@@ -1941,33 +1919,17 @@ TEST_F(TRACE_syscall, syscall_redirected)
 
 TEST_F(TRACE_syscall, syscall_errno)
 {
-       long ret;
-
-       ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-       ASSERT_EQ(0, ret);
-
-       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
-       ASSERT_EQ(0, ret);
-
-       /* openat has been skipped and an errno return. */
+       /* Tracer should skip the open syscall, resulting in ESRCH. */
        EXPECT_SYSCALL_RETURN(-ESRCH, syscall(__NR_openat));
 }
 
 TEST_F(TRACE_syscall, syscall_faked)
 {
-       long ret;
-
-       ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-       ASSERT_EQ(0, ret);
-
-       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
-       ASSERT_EQ(0, ret);
-
-       /* gettid has been skipped and an altered return value stored. */
+       /* Tracer skips the gettid syscall and store altered return value. */
        EXPECT_SYSCALL_RETURN(45000, syscall(__NR_gettid));
 }
 
-TEST_F(TRACE_syscall, skip_after_RET_TRACE)
+TEST_F(TRACE_syscall, skip_after)
 {
        struct sock_filter filter[] = {
                BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
@@ -1982,14 +1944,7 @@ TEST_F(TRACE_syscall, skip_after_RET_TRACE)
        };
        long ret;
 
-       ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-       ASSERT_EQ(0, ret);
-
-       /* Install fixture filter. */
-       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
-       ASSERT_EQ(0, ret);
-
-       /* Install "errno on getppid" filter. */
+       /* Install additional "errno on getppid" filter. */
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
        ASSERT_EQ(0, ret);
 
@@ -1999,7 +1954,7 @@ TEST_F(TRACE_syscall, skip_after_RET_TRACE)
        EXPECT_EQ(EPERM, errno);
 }
 
-TEST_F_SIGNAL(TRACE_syscall, kill_after_RET_TRACE, SIGSYS)
+TEST_F_SIGNAL(TRACE_syscall, kill_after, SIGSYS)
 {
        struct sock_filter filter[] = {
                BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
@@ -2014,77 +1969,7 @@ TEST_F_SIGNAL(TRACE_syscall, kill_after_RET_TRACE, SIGSYS)
        };
        long ret;
 
-       ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-       ASSERT_EQ(0, ret);
-
-       /* Install fixture filter. */
-       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
-       ASSERT_EQ(0, ret);
-
-       /* Install "death on getppid" filter. */
-       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
-       ASSERT_EQ(0, ret);
-
-       /* Tracer will redirect getpid to getppid, and we should die. */
-       EXPECT_NE(self->mypid, syscall(__NR_getpid));
-}
-
-TEST_F(TRACE_syscall, skip_after_ptrace)
-{
-       struct sock_filter filter[] = {
-               BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
-                       offsetof(struct seccomp_data, nr)),
-               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
-               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | EPERM),
-               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-       };
-       struct sock_fprog prog = {
-               .len = (unsigned short)ARRAY_SIZE(filter),
-               .filter = filter,
-       };
-       long ret;
-
-       /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
-       teardown_trace_fixture(_metadata, self->tracer);
-       self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
-                                          true);
-
-       ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-       ASSERT_EQ(0, ret);
-
-       /* Install "errno on getppid" filter. */
-       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
-       ASSERT_EQ(0, ret);
-
-       /* Tracer will redirect getpid to getppid, and we should see EPERM. */
-       EXPECT_EQ(-1, syscall(__NR_getpid));
-       EXPECT_EQ(EPERM, errno);
-}
-
-TEST_F_SIGNAL(TRACE_syscall, kill_after_ptrace, SIGSYS)
-{
-       struct sock_filter filter[] = {
-               BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
-                       offsetof(struct seccomp_data, nr)),
-               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
-               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
-               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-       };
-       struct sock_fprog prog = {
-               .len = (unsigned short)ARRAY_SIZE(filter),
-               .filter = filter,
-       };
-       long ret;
-
-       /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
-       teardown_trace_fixture(_metadata, self->tracer);
-       self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
-                                          true);
-
-       ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-       ASSERT_EQ(0, ret);
-
-       /* Install "death on getppid" filter. */
+       /* Install additional "death on getppid" filter. */
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
        ASSERT_EQ(0, ret);