Commit 23fcb62b authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller
Browse files

selftests: tls: add tests for poll behavior



Make sure we don't generate premature POLLIN events.

Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 121dca78
Loading
Loading
Loading
Loading
+131 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/tcp.h>
#include <linux/socket.h>

#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/sendfile.h>
#include <sys/socket.h>
@@ -1637,6 +1638,136 @@ TEST_F(tls_err, timeo)
	}
}

TEST_F(tls_err, poll_partial_rec)
{
	struct pollfd pfd = { };
	ssize_t rec_len;
	char rec[256];
	char buf[128];

	if (self->notls)
		SKIP(return, "no TLS support");

	pfd.fd = self->cfd2;
	pfd.events = POLLIN;
	EXPECT_EQ(poll(&pfd, 1, 1), 0);

	memrnd(buf, sizeof(buf));
	EXPECT_EQ(send(self->fd, buf, sizeof(buf), 0), sizeof(buf));
	rec_len = recv(self->cfd, rec, sizeof(rec), 0);
	EXPECT_GT(rec_len, sizeof(buf));

	/* Write 100B, not the full record ... */
	EXPECT_EQ(send(self->fd2, rec, 100, 0), 100);
	/* ... no full record should mean no POLLIN */
	pfd.fd = self->cfd2;
	pfd.events = POLLIN;
	EXPECT_EQ(poll(&pfd, 1, 1), 0);
	/* Now write the rest, and it should all pop out of the other end. */
	EXPECT_EQ(send(self->fd2, rec + 100, rec_len - 100, 0), rec_len - 100);
	pfd.fd = self->cfd2;
	pfd.events = POLLIN;
	EXPECT_EQ(poll(&pfd, 1, 1), 1);
	EXPECT_EQ(recv(self->cfd2, rec, sizeof(rec), 0), sizeof(buf));
	EXPECT_EQ(memcmp(buf, rec, sizeof(buf)), 0);
}

TEST_F(tls_err, epoll_partial_rec)
{
	struct epoll_event ev, events[10];
	ssize_t rec_len;
	char rec[256];
	char buf[128];
	int epollfd;

	if (self->notls)
		SKIP(return, "no TLS support");

	epollfd = epoll_create1(0);
	ASSERT_GE(epollfd, 0);

	memset(&ev, 0, sizeof(ev));
	ev.events = EPOLLIN;
	ev.data.fd = self->cfd2;
	ASSERT_GE(epoll_ctl(epollfd, EPOLL_CTL_ADD, self->cfd2, &ev), 0);

	EXPECT_EQ(epoll_wait(epollfd, events, 10, 0), 0);

	memrnd(buf, sizeof(buf));
	EXPECT_EQ(send(self->fd, buf, sizeof(buf), 0), sizeof(buf));
	rec_len = recv(self->cfd, rec, sizeof(rec), 0);
	EXPECT_GT(rec_len, sizeof(buf));

	/* Write 100B, not the full record ... */
	EXPECT_EQ(send(self->fd2, rec, 100, 0), 100);
	/* ... no full record should mean no POLLIN */
	EXPECT_EQ(epoll_wait(epollfd, events, 10, 0), 0);
	/* Now write the rest, and it should all pop out of the other end. */
	EXPECT_EQ(send(self->fd2, rec + 100, rec_len - 100, 0), rec_len - 100);
	EXPECT_EQ(epoll_wait(epollfd, events, 10, 0), 1);
	EXPECT_EQ(recv(self->cfd2, rec, sizeof(rec), 0), sizeof(buf));
	EXPECT_EQ(memcmp(buf, rec, sizeof(buf)), 0);

	close(epollfd);
}

TEST_F(tls_err, poll_partial_rec_async)
{
	struct pollfd pfd = { };
	ssize_t rec_len;
	char rec[256];
	char buf[128];
	char token;
	int p[2];
	int ret;

	if (self->notls)
		SKIP(return, "no TLS support");

	ASSERT_GE(pipe(p), 0);

	memrnd(buf, sizeof(buf));
	EXPECT_EQ(send(self->fd, buf, sizeof(buf), 0), sizeof(buf));
	rec_len = recv(self->cfd, rec, sizeof(rec), 0);
	EXPECT_GT(rec_len, sizeof(buf));

	ret = fork();
	ASSERT_GE(ret, 0);

	if (ret) {
		int status, pid2;

		close(p[1]);
		usleep(1000); /* Give child a head start */

		EXPECT_EQ(send(self->fd2, rec, 100, 0), 100);

		EXPECT_EQ(read(p[0], &token, 1), 1); /* Barrier #1 */

		EXPECT_EQ(send(self->fd2, rec + 100, rec_len - 100, 0),
			  rec_len - 100);

		pid2 = wait(&status);
		EXPECT_EQ(pid2, ret);
		EXPECT_EQ(status, 0);
	} else {
		close(p[0]);

		/* Child should sleep in poll(), never get a wake */
		pfd.fd = self->cfd2;
		pfd.events = POLLIN;
		EXPECT_EQ(poll(&pfd, 1, 5), 0);

		EXPECT_EQ(write(p[1], &token, 1), 1); /* Barrier #1 */

		pfd.fd = self->cfd2;
		pfd.events = POLLIN;
		EXPECT_EQ(poll(&pfd, 1, 5), 1);

		exit(!_metadata->passed);
	}
}

TEST(non_established) {
	struct tls12_crypto_info_aes_gcm_256 tls12;
	struct sockaddr_in addr;