Test that SECCOMP_IOCTL_NOTIF_RECV on a seccomp fd with zero users returns -ENOTCONN, both in blocking and in non-blocking mode. Also test that SECCOMP_IOCTL_NOTIF_RECV on a seccomp fd with no active notifications returns -ENOENT in non-blocking mode. Signed-off-by: Jann Horn <jannh@xxxxxxxxxx> --- tools/testing/selftests/seccomp/seccomp_bpf.c | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c index 5318f9cb1aec..8214c431ad4b 100644 --- a/tools/testing/selftests/seccomp/seccomp_bpf.c +++ b/tools/testing/selftests/seccomp/seccomp_bpf.c @@ -28,6 +28,7 @@ #include <linux/prctl.h> #include <linux/ptrace.h> #include <linux/seccomp.h> +#include <linux/futex.h> #include <pthread.h> #include <semaphore.h> #include <signal.h> @@ -315,6 +316,35 @@ static int __filecmp(pid_t pid1, pid_t pid2, int fd1, int fd2) } \ _ret; }) +static void store_and_wake(int *ptr, int value) +{ + __atomic_store(ptr, &value, __ATOMIC_RELEASE); + if (syscall(__NR_futex, ptr, FUTEX_WAKE, INT_MAX, NULL, NULL, 0) == -1) { + perror("FUTEX_WAKE failed unexpectedly"); + exit(EXIT_FAILURE); + } +} + +static int wait_and_load(int *ptr, int placeholder) +{ + int futex_ret; + int value; + +retry: + futex_ret = syscall(__NR_futex, ptr, FUTEX_WAIT, placeholder, NULL, + NULL, 0); + if (futex_ret == -1 && errno != EAGAIN) { + if (errno == EINTR) + goto retry; + perror("FUTEX_WAIT failed unexpectedly"); + exit(EXIT_FAILURE); + } + value = __atomic_load_n(ptr, __ATOMIC_ACQUIRE); + if (value == placeholder) + goto retry; + return value; +} + TEST(kcmp) { int ret; @@ -4160,6 +4190,103 @@ TEST(user_notification_addfd_rlimit) close(memfd); } +TEST(user_notification_recv_dead) +{ + pid_t pid; + int status; + struct __clone_args args = { + .flags = CLONE_FILES, + .exit_signal = SIGCHLD, + }; + struct seccomp_notif notif = {}; + struct shared_data { + int notif_fd; + } *shared_data; + + shared_data = mmap(NULL, sizeof(struct shared_data), + PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_SHARED, + -1, 0); + ASSERT_NE(NULL, shared_data); + ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { + TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!"); + } + + pid = sys_clone3(&args, sizeof(args)); + ASSERT_GE(pid, 0); + + if (pid == 0) { + shared_data->notif_fd = user_notif_syscall( + __NR_mknodat, SECCOMP_FILTER_FLAG_NEW_LISTENER); + if (shared_data->notif_fd < 0) + _exit(EXIT_FAILURE); + + _exit(EXIT_SUCCESS); + } + + EXPECT_EQ(waitpid(pid, &status, 0), pid); + EXPECT_EQ(true, WIFEXITED(status)); + EXPECT_EQ(0, WEXITSTATUS(status)); + + /* non-blocking recv */ + EXPECT_EQ(-1, ioctl(shared_data->notif_fd, SECCOMP_IOCTL_NOTIF_RECV, ¬if)); + EXPECT_EQ(ENOTCONN, errno); + + /* blocking recv */ + set_blocking(shared_data->notif_fd); + EXPECT_EQ(-1, ioctl(shared_data->notif_fd, SECCOMP_IOCTL_NOTIF_RECV, ¬if)); + EXPECT_EQ(ENOTCONN, errno); +} + +TEST(user_notification_recv_nonblock) +{ + pid_t pid; + struct __clone_args args = { + .flags = CLONE_FILES, + .exit_signal = SIGCHLD, + }; + struct seccomp_notif notif = {}; + struct shared_data { + int notif_fd; + } *shared_data; + + shared_data = mmap(NULL, sizeof(struct shared_data), + PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_SHARED, + -1, 0); + ASSERT_NE(NULL, shared_data); + shared_data->notif_fd = -1; + + ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { + TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!"); + } + + pid = sys_clone3(&args, sizeof(args)); + ASSERT_GE(pid, 0); + + if (pid == 0) { + int fd; + + fd = user_notif_syscall(__NR_mknodat, + SECCOMP_FILTER_FLAG_NEW_LISTENER); + if (fd < 0) { + store_and_wake(&shared_data->notif_fd, -2); + _exit(EXIT_FAILURE); + } + store_and_wake(&shared_data->notif_fd, fd); + + while (1) + pause(); + } + + wait_and_load(&shared_data->notif_fd, -1); + + /* non-blocking recv */ + EXPECT_EQ(-1, ioctl(shared_data->notif_fd, SECCOMP_IOCTL_NOTIF_RECV, + ¬if)); + EXPECT_EQ(ENOENT, errno); + + kill(pid, SIGKILL); +} + /* * TODO: * - expand NNP testing -- 2.29.1.341.ge80a0c044ae-goog _______________________________________________ Containers mailing list Containers@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linuxfoundation.org/mailman/listinfo/containers