diff options
author | Andrei Vagin <avagin@google.com> | 2024-06-28 02:10:14 +0000 |
---|---|---|
committer | Kees Cook <kees@kernel.org> | 2024-06-28 09:37:11 -0700 |
commit | f0c508faea645da58d6ae6b644a1b68020d5a9d2 (patch) | |
tree | 69115548f1a4f1b9fd5aa6f61e8b44eb9802afc9 | |
parent | 39a73b4aa69aeb1adcf9960710c12842a4092b7a (diff) | |
download | lwn-f0c508faea645da58d6ae6b644a1b68020d5a9d2.tar.gz lwn-f0c508faea645da58d6ae6b644a1b68020d5a9d2.zip |
selftests/seccomp: check that a zombie leader doesn't affect others
Ensure that a dead thread leader doesn't prevent installing new filters
with SECCOMP_FILTER_FLAG_TSYNC from other threads.
Signed-off-by: Andrei Vagin <avagin@google.com>
Link: https://lore.kernel.org/r/20240628021014.231976-5-avagin@google.com
Reviewed-by: Tycho Andersen <tandersen@netflix.com>
Signed-off-by: Kees Cook <kees@kernel.org>
-rw-r--r-- | tools/testing/selftests/seccomp/seccomp_bpf.c | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c index 390781d7c951..e3f97f90d8db 100644 --- a/tools/testing/selftests/seccomp/seccomp_bpf.c +++ b/tools/testing/selftests/seccomp/seccomp_bpf.c @@ -4809,6 +4809,83 @@ TEST(user_notification_wait_killable_fatal) EXPECT_EQ(SIGTERM, WTERMSIG(status)); } +struct tsync_vs_thread_leader_args { + pthread_t leader; +}; + +static void *tsync_vs_dead_thread_leader_sibling(void *_args) +{ + struct sock_filter allow_filter[] = { + BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), + }; + struct sock_fprog allow_prog = { + .len = (unsigned short)ARRAY_SIZE(allow_filter), + .filter = allow_filter, + }; + struct tsync_vs_thread_leader_args *args = _args; + void *retval; + long ret; + + ret = pthread_join(args->leader, &retval); + if (ret) + exit(1); + if (retval != _args) + exit(2); + ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC, &allow_prog); + if (ret) + exit(3); + + exit(0); +} + +/* + * Ensure that a dead thread leader doesn't prevent installing new filters with + * SECCOMP_FILTER_FLAG_TSYNC from other threads. + */ +TEST(tsync_vs_dead_thread_leader) +{ + int status; + pid_t pid; + long ret; + + ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); + ASSERT_EQ(0, ret) { + TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!"); + } + + pid = fork(); + ASSERT_GE(pid, 0); + + if (pid == 0) { + struct sock_filter allow_filter[] = { + BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), + }; + struct sock_fprog allow_prog = { + .len = (unsigned short)ARRAY_SIZE(allow_filter), + .filter = allow_filter, + }; + struct tsync_vs_thread_leader_args *args; + pthread_t sibling; + + args = malloc(sizeof(*args)); + ASSERT_NE(NULL, args); + args->leader = pthread_self(); + + ret = pthread_create(&sibling, NULL, + tsync_vs_dead_thread_leader_sibling, args); + ASSERT_EQ(0, ret); + + /* Install a new filter just to the leader thread. */ + ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &allow_prog); + ASSERT_EQ(0, ret); + pthread_exit(args); + exit(1); + } + + EXPECT_EQ(pid, waitpid(pid, &status, 0)); + EXPECT_EQ(0, status); +} + /* * TODO: * - expand NNP testing |