Skip to content

Commit

Permalink
selftests/seccomp: Add test for unknown SECCOMP_RET kill behavior
Browse files Browse the repository at this point in the history
While we were testing for the behavior of unknown seccomp filter return
values, there was no test for how it acted in a thread group. Add a test
in the thread group tests for this.

Reviewed-by: Shuah Khan <skhan@linuxfoundation.org>
Acked-by: Christian Brauner <christian.brauner@ubuntu.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
  • Loading branch information
Kees Cook committed Sep 8, 2020
1 parent 4d671d9 commit 3932fce
Showing 1 changed file with 37 additions and 6 deletions.
43 changes: 37 additions & 6 deletions tools/testing/selftests/seccomp/seccomp_bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -774,8 +774,15 @@ void *kill_thread(void *data)
return (void *)SIBLING_EXIT_UNKILLED;
}

enum kill_t {
KILL_THREAD,
KILL_PROCESS,
RET_UNKNOWN
};

/* Prepare a thread that will kill itself or both of us. */
void kill_thread_or_group(struct __test_metadata *_metadata, bool kill_process)
void kill_thread_or_group(struct __test_metadata *_metadata,
enum kill_t kill_how)
{
pthread_t thread;
void *status;
Expand All @@ -791,11 +798,12 @@ void kill_thread_or_group(struct __test_metadata *_metadata, bool kill_process)
.len = (unsigned short)ARRAY_SIZE(filter_thread),
.filter = filter_thread,
};
int kill = kill_how == KILL_PROCESS ? SECCOMP_RET_KILL_PROCESS : 0xAAAAAAAAA;
struct sock_filter filter_process[] = {
BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
offsetof(struct seccomp_data, nr)),
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_prctl, 0, 1),
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL_PROCESS),
BPF_STMT(BPF_RET|BPF_K, kill),
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
};
struct sock_fprog prog_process = {
Expand All @@ -808,13 +816,15 @@ void kill_thread_or_group(struct __test_metadata *_metadata, bool kill_process)
}

ASSERT_EQ(0, seccomp(SECCOMP_SET_MODE_FILTER, 0,
kill_process ? &prog_process : &prog_thread));
kill_how == KILL_THREAD ? &prog_thread
: &prog_process));

/*
* Add the KILL_THREAD rule again to make sure that the KILL_PROCESS
* flag cannot be downgraded by a new filter.
*/
ASSERT_EQ(0, seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog_thread));
if (kill_how == KILL_PROCESS)
ASSERT_EQ(0, seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog_thread));

/* Start a thread that will exit immediately. */
ASSERT_EQ(0, pthread_create(&thread, NULL, kill_thread, (void *)false));
Expand Down Expand Up @@ -842,7 +852,7 @@ TEST(KILL_thread)
child_pid = fork();
ASSERT_LE(0, child_pid);
if (child_pid == 0) {
kill_thread_or_group(_metadata, false);
kill_thread_or_group(_metadata, KILL_THREAD);
_exit(38);
}

Expand All @@ -861,7 +871,7 @@ TEST(KILL_process)
child_pid = fork();
ASSERT_LE(0, child_pid);
if (child_pid == 0) {
kill_thread_or_group(_metadata, true);
kill_thread_or_group(_metadata, KILL_PROCESS);
_exit(38);
}

Expand All @@ -872,6 +882,27 @@ TEST(KILL_process)
ASSERT_EQ(SIGSYS, WTERMSIG(status));
}

TEST(KILL_unknown)
{
int status;
pid_t child_pid;

child_pid = fork();
ASSERT_LE(0, child_pid);
if (child_pid == 0) {
kill_thread_or_group(_metadata, RET_UNKNOWN);
_exit(38);
}

ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));

/* If the entire process was killed, we'll see SIGSYS. */
EXPECT_TRUE(WIFSIGNALED(status)) {
TH_LOG("Unknown SECCOMP_RET is only killing the thread?");
}
ASSERT_EQ(SIGSYS, WTERMSIG(status));
}

/* TODO(wad) add 64-bit versus 32-bit arg tests. */
TEST(arg_out_of_range)
{
Expand Down

0 comments on commit 3932fce

Please sign in to comment.