lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20210112003017.4010304-2-willemdebruijn.kernel@gmail.com>
Date:   Mon, 11 Jan 2021 19:30:12 -0500
From:   Willem de Bruijn <willemdebruijn.kernel@...il.com>
To:     linux-fsdevel@...r.kernel.org
Cc:     linux-kernel@...r.kernel.org, viro@...iv.linux.org.uk,
        akpm@...ux-foundation.org, willy@...radead.org, arnd@...nel.org,
        Willem de Bruijn <willemb@...gle.com>
Subject: [PATCH 1/6] selftests/filesystems: add initial select and poll selftest

From: Willem de Bruijn <willemb@...gle.com>

Add initial code coverage for select, pselect, poll and ppoll.

Open a socketpair and wait for a read event.
1. run with data waiting
2. run to timeout, if a (short) timeout is specified.

Also optionally pass sigset to pselect and ppoll, to exercise
all datapaths. Build with -m32, -mx32 and -m64 to cover all the
various compat and 32/64-bit time syscall implementations.

Signed-off-by: Willem de Bruijn <willemb@...gle.com>
---
 .../testing/selftests/filesystems/.gitignore  |   1 +
 tools/testing/selftests/filesystems/Makefile  |   2 +-
 .../selftests/filesystems/selectpoll.c        | 207 ++++++++++++++++++
 3 files changed, 209 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/filesystems/selectpoll.c

diff --git a/tools/testing/selftests/filesystems/.gitignore b/tools/testing/selftests/filesystems/.gitignore
index f0c0ff20d6cf..d4a2e50475ea 100644
--- a/tools/testing/selftests/filesystems/.gitignore
+++ b/tools/testing/selftests/filesystems/.gitignore
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-only
 dnotify_test
 devpts_pts
+selectpoll
diff --git a/tools/testing/selftests/filesystems/Makefile b/tools/testing/selftests/filesystems/Makefile
index 129880fb42d3..8de184865fa4 100644
--- a/tools/testing/selftests/filesystems/Makefile
+++ b/tools/testing/selftests/filesystems/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 
 CFLAGS += -I../../../../usr/include/
-TEST_GEN_PROGS := devpts_pts
+TEST_GEN_PROGS := devpts_pts selectpoll
 TEST_GEN_PROGS_EXTENDED := dnotify_test
 
 include ../lib.mk
diff --git a/tools/testing/selftests/filesystems/selectpoll.c b/tools/testing/selftests/filesystems/selectpoll.c
new file mode 100644
index 000000000000..315da0786a6c
--- /dev/null
+++ b/tools/testing/selftests/filesystems/selectpoll.c
@@ -0,0 +1,207 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#define _GNU_SOURCE
+#include <asm/unistd.h>
+#include <poll.h>
+#include <unistd.h>
+#include <assert.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include "../kselftest_harness.h"
+
+const unsigned long timeout_us = 5UL * 1000;
+const unsigned long timeout_ns = timeout_us * 1000;
+
+/* (p)select: basic invocation, optionally with data waiting */
+
+FIXTURE(select_basic)
+{
+	fd_set readfds;
+	int sfd[2];
+};
+
+FIXTURE_SETUP(select_basic)
+{
+	ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, self->sfd), 0);
+
+	FD_ZERO(&self->readfds);
+	FD_SET(self->sfd[0], &self->readfds);
+	FD_SET(self->sfd[1], &self->readfds);
+}
+
+FIXTURE_TEARDOWN(select_basic)
+{
+	/* FD_ISSET(self->sfd[0] tested in TEST_F: depends on timeout */
+	ASSERT_EQ(FD_ISSET(self->sfd[1], &self->readfds), 0);
+
+	EXPECT_EQ(close(self->sfd[0]), 0);
+	EXPECT_EQ(close(self->sfd[1]), 0);
+}
+
+TEST_F(select_basic, select)
+{
+	ASSERT_EQ(write(self->sfd[1], "w", 1), 1);
+	ASSERT_EQ(select(self->sfd[1] + 1, &self->readfds,
+			 NULL, NULL, NULL), 1);
+	ASSERT_NE(FD_ISSET(self->sfd[0], &self->readfds), 0);
+}
+
+TEST_F(select_basic, select_with_timeout)
+{
+	struct timeval tv = { .tv_usec = timeout_us };
+
+	ASSERT_EQ(write(self->sfd[1], "w", 1), 1);
+	ASSERT_EQ(select(self->sfd[1] + 1, &self->readfds,
+			 NULL, NULL, &tv), 1);
+	ASSERT_GE(tv.tv_usec, 1000);
+	ASSERT_NE(FD_ISSET(self->sfd[0], &self->readfds), 0);
+}
+
+TEST_F(select_basic, select_timeout)
+{
+	struct timeval tv = { .tv_usec = timeout_us };
+
+	ASSERT_EQ(select(self->sfd[1] + 1, &self->readfds,
+			 NULL, NULL, &tv), 0);
+	ASSERT_EQ(FD_ISSET(self->sfd[0], &self->readfds), 0);
+}
+
+TEST_F(select_basic, pselect)
+{
+	ASSERT_EQ(write(self->sfd[1], "w", 1), 1);
+	ASSERT_EQ(pselect(self->sfd[1] + 1, &self->readfds,
+			  NULL, NULL, NULL, NULL), 1);
+	ASSERT_NE(FD_ISSET(self->sfd[0], &self->readfds), 0);
+}
+
+TEST_F(select_basic, pselect_with_timeout)
+{
+	struct timespec ts = { .tv_nsec = timeout_ns };
+
+	ASSERT_EQ(write(self->sfd[1], "w", 1), 1);
+	ASSERT_EQ(pselect(self->sfd[1] + 1, &self->readfds,
+			  NULL, NULL, &ts, NULL), 1);
+	ASSERT_GE(ts.tv_nsec, 1000);
+	ASSERT_NE(FD_ISSET(self->sfd[0], &self->readfds), 0);
+}
+
+TEST_F(select_basic, pselect_timeout)
+{
+	struct timespec ts = { .tv_nsec = timeout_ns };
+
+	ASSERT_EQ(pselect(self->sfd[1] + 1, &self->readfds,
+			  NULL, NULL, &ts, NULL), 0);
+	ASSERT_EQ(FD_ISSET(self->sfd[0], &self->readfds), 0);
+}
+
+TEST_F(select_basic, pselect_sigset_with_timeout)
+{
+	struct timespec ts = { .tv_nsec = timeout_ns };
+	sigset_t sigmask;
+
+	sigemptyset(&sigmask);
+	sigaddset(&sigmask, SIGUSR1);
+	sigprocmask(SIG_SETMASK, &sigmask, NULL);
+	sigemptyset(&sigmask);
+
+	ASSERT_EQ(write(self->sfd[1], "w", 1), 1);
+	ASSERT_EQ(pselect(self->sfd[1] + 1, &self->readfds,
+			  NULL, NULL, &ts, &sigmask), 1);
+	ASSERT_GE(ts.tv_nsec, 1000);
+	ASSERT_NE(FD_ISSET(self->sfd[0], &self->readfds), 0);
+}
+
+/* (p)poll: basic invocation with data waiting */
+
+FIXTURE(poll_basic)
+{
+	struct pollfd pfds[2];
+	int sfd[2];
+};
+
+FIXTURE_SETUP(poll_basic)
+{
+	ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, self->sfd), 0);
+
+	self->pfds[0].events = POLLIN;
+	self->pfds[0].revents = 0;
+	self->pfds[0].fd = self->sfd[0];
+
+	self->pfds[1].events = POLLIN;
+	self->pfds[1].revents = 0;
+	self->pfds[1].fd = self->sfd[1];
+}
+
+FIXTURE_TEARDOWN(poll_basic)
+{
+	/* FD_ISSET(self->pfds[0] tested in TEST_F: depends on timeout */
+	EXPECT_EQ(self->pfds[1].revents & POLLIN, 0);
+
+	EXPECT_EQ(close(self->sfd[0]), 0);
+	EXPECT_EQ(close(self->sfd[1]), 0);
+}
+
+TEST_F(poll_basic, poll)
+{
+	ASSERT_EQ(write(self->sfd[1], "w", 1), 1);
+	EXPECT_EQ(poll(self->pfds, ARRAY_SIZE(self->pfds), 0), 1);
+	EXPECT_EQ(self->pfds[0].revents & POLLIN, POLLIN);
+}
+
+TEST_F(poll_basic, poll_with_timeout)
+{
+	ASSERT_EQ(write(self->sfd[1], "w", 1), 1);
+	EXPECT_EQ(poll(self->pfds, ARRAY_SIZE(self->pfds), 1001), 1);
+	EXPECT_EQ(self->pfds[0].revents & POLLIN, POLLIN);
+}
+
+TEST_F(poll_basic, poll_timeout)
+{
+	EXPECT_EQ(poll(self->pfds, ARRAY_SIZE(self->pfds), 1001), 0);
+	EXPECT_EQ(self->pfds[0].revents & POLLIN, 0);
+}
+
+TEST_F(poll_basic, ppoll)
+{
+	ASSERT_EQ(write(self->sfd[1], "w", 1), 1);
+	EXPECT_EQ(ppoll(self->pfds, ARRAY_SIZE(self->pfds), NULL, NULL), 1);
+	EXPECT_EQ(self->pfds[0].revents & POLLIN, POLLIN);
+}
+
+TEST_F(poll_basic, ppoll_with_timeout)
+{
+	struct timespec ts = { .tv_nsec = timeout_ns };
+
+	ASSERT_EQ(write(self->sfd[1], "w", 1), 1);
+	EXPECT_EQ(ppoll(self->pfds, ARRAY_SIZE(self->pfds), &ts, NULL), 1);
+	ASSERT_GE(ts.tv_nsec, 1000);
+	EXPECT_EQ(self->pfds[0].revents & POLLIN, POLLIN);
+}
+
+TEST_F(poll_basic, ppoll_timeout)
+{
+	struct timespec ts = { .tv_nsec = timeout_ns };
+
+	EXPECT_EQ(ppoll(self->pfds, ARRAY_SIZE(self->pfds), &ts, NULL), 0);
+	EXPECT_EQ(self->pfds[0].revents & POLLIN, 0);
+}
+
+TEST_F(poll_basic, ppoll_sigset_with_timeout)
+{
+	struct timespec ts = { .tv_nsec = timeout_ns };
+	sigset_t sigmask;
+
+	sigemptyset(&sigmask);
+	sigaddset(&sigmask, SIGUSR1);
+	sigprocmask(SIG_SETMASK, &sigmask, NULL);
+	sigemptyset(&sigmask);
+
+	ASSERT_EQ(write(self->sfd[1], "w", 1), 1);
+	EXPECT_EQ(ppoll(self->pfds, ARRAY_SIZE(self->pfds), &ts, &sigmask), 1);
+	ASSERT_GE(ts.tv_nsec, 1000);
+	EXPECT_EQ(self->pfds[0].revents & POLLIN, POLLIN);
+}
+
+TEST_HARNESS_MAIN
-- 
2.30.0.284.gd98b1dd5eaa7-goog

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ