[PATCH v4 4/6] selftest/landlock: Test file_send_sigiotask by sending out-of-bound message
From: Tahera Fahimi <hidden>
Date: 2024-09-06 21:30:20
Also in:
linux-security-module, lkml
Subsystem:
kernel selftest framework, landlock security module, the rest · Maintainers:
Shuah Khan, Mickaël Salaün, Linus Torvalds
This patch adds a test to verify handling the signal scoping mechanism in file_send_sigiotask by triggering SIGURG through receiving an out-of-bound message in UNIX sockets. Signed-off-by: Tahera Fahimi <redacted> --- V4: * Using pipe instead of Poll for synchronization. --- .../selftests/landlock/scoped_signal_test.c | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+)
diff --git a/tools/testing/selftests/landlock/scoped_signal_test.c b/tools/testing/selftests/landlock/scoped_signal_test.c
index c71fb83b7147..630f3a515731 100644
--- a/tools/testing/selftests/landlock/scoped_signal_test.c
+++ b/tools/testing/selftests/landlock/scoped_signal_test.c@@ -269,4 +269,103 @@ TEST(signal_scoping_threads) EXPECT_EQ(0, close(thread_pipe[1])); } +#define SOCKET_PATH "/tmp/unix_sock_test" + +const short backlog = 10; + +static volatile sig_atomic_t signal_received; + +static void handle_sigurg(int sig) +{ + if (sig == SIGURG) + signal_received = 1; + else + signal_received = -1; +} + +static int setup_signal_handler(int signal) +{ + struct sigaction sa; + + sa.sa_handler = handle_sigurg; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_SIGINFO | SA_RESTART; + return sigaction(SIGURG, &sa, NULL); +} + +/* + * Sending an out of bound message will trigger the SIGURG signal + * through file_send_sigiotask. + */ +TEST(test_sigurg_socket) +{ + int sock_fd, recv_sock; + struct sockaddr_un addr, paddr; + socklen_t size; + char oob_buf, buffer; + int status; + int pipe_parent[2], pipe_child[2]; + pid_t child; + + ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC)); + ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC)); + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", SOCKET_PATH); + unlink(SOCKET_PATH); + size = sizeof(addr); + + child = fork(); + ASSERT_LE(0, child); + if (child == 0) { + oob_buf = '.'; + + ASSERT_EQ(0, close(pipe_parent[1])); + ASSERT_EQ(0, close(pipe_child[0])); + + sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); + ASSERT_NE(-1, sock_fd); + + ASSERT_EQ(1, read(pipe_parent[0], &buffer, 1)); + ASSERT_EQ(0, connect(sock_fd, &addr, sizeof(addr))); + + ASSERT_EQ(1, read(pipe_parent[0], &buffer, 1)); + ASSERT_NE(-1, send(sock_fd, &oob_buf, 1, MSG_OOB)); + ASSERT_EQ(1, write(pipe_child[1], ".", 1)); + + EXPECT_EQ(0, close(sock_fd)); + + _exit(_metadata->exit_code); + return; + } + ASSERT_EQ(0, close(pipe_parent[0])); + ASSERT_EQ(0, close(pipe_child[1])); + + sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); + ASSERT_NE(-1, sock_fd); + ASSERT_EQ(0, bind(sock_fd, &addr, size)); + ASSERT_EQ(0, listen(sock_fd, backlog)); + + ASSERT_NE(-1, setup_signal_handler(SIGURG)); + ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); + recv_sock = accept(sock_fd, &paddr, &size); + ASSERT_NE(-1, recv_sock); + + create_scoped_domain(_metadata, LANDLOCK_SCOPED_SIGNAL); + + ASSERT_NE(-1, fcntl(recv_sock, F_SETOWN, getpid())); + ASSERT_EQ(1, write(pipe_parent[1], ".", 1)); + ASSERT_EQ(1, read(pipe_child[0], &buffer, 1)); + ASSERT_EQ(1, recv(recv_sock, &oob_buf, 1, MSG_OOB)); + + ASSERT_EQ(1, signal_received); + EXPECT_EQ(0, close(sock_fd)); + EXPECT_EQ(0, close(recv_sock)); + ASSERT_EQ(child, waitpid(child, &status, 0)); + if (WIFSIGNALED(status) || !WIFEXITED(status) || + WEXITSTATUS(status) != EXIT_SUCCESS) + _metadata->exit_code = KSFT_FAIL; +} + TEST_HARNESS_MAIN
--
2.34.1