net/tls(TLS_SW): Add selftest for 'chunked' sendfile test
authorPooja Trivedi <poojatrivedi@gmail.com>
Fri, 5 Jun 2020 16:01:18 +0000 (16:01 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 9 Jun 2020 02:01:54 +0000 (19:01 -0700)
This selftest tests for cases where sendfile's 'count'
parameter is provided with a size greater than the intended
file size.

Motivation: When sendfile is provided with 'count' parameter
value that is greater than the size of the file, kTLS example
fails to send the file correctly. Last chunk of the file is
not sent, and the data integrity is compromised.
The reason is that the last chunk has MSG_MORE flag set
because of which it gets added to pending records, but is
not pushed.
Note that if user space were to send SSL_shutdown control
message, pending records would get flushed and the issue
would not happen. So a shutdown control message following
sendfile can mask the issue.

Signed-off-by: Pooja Trivedi <pooja.trivedi@stackpath.com>
Signed-off-by: Mallesham Jatharkonda <mallesham.jatharkonda@oneconvergence.com>
Signed-off-by: Josh Tway <josh.tway@stackpath.com>
Reviewed-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
tools/testing/selftests/net/tls.c

index c5282e62df75c276d019793034d2da0efb76ed50..b599f1fa99b55aba5d359163f35a9fc32713e5ee 100644 (file)
@@ -213,6 +213,64 @@ TEST_F(tls, send_then_sendfile)
        EXPECT_EQ(recv(self->cfd, buf, st.st_size, MSG_WAITALL), st.st_size);
 }
 
+static void chunked_sendfile(struct __test_metadata *_metadata,
+                            struct _test_data_tls *self,
+                            uint16_t chunk_size,
+                            uint16_t extra_payload_size)
+{
+       char buf[TLS_PAYLOAD_MAX_LEN];
+       uint16_t test_payload_size;
+       int size = 0;
+       int ret;
+       char filename[] = "/tmp/mytemp.XXXXXX";
+       int fd = mkstemp(filename);
+       off_t offset = 0;
+
+       unlink(filename);
+       ASSERT_GE(fd, 0);
+       EXPECT_GE(chunk_size, 1);
+       test_payload_size = chunk_size + extra_payload_size;
+       ASSERT_GE(TLS_PAYLOAD_MAX_LEN, test_payload_size);
+       memset(buf, 1, test_payload_size);
+       size = write(fd, buf, test_payload_size);
+       EXPECT_EQ(size, test_payload_size);
+       fsync(fd);
+
+       while (size > 0) {
+               ret = sendfile(self->fd, fd, &offset, chunk_size);
+               EXPECT_GE(ret, 0);
+               size -= ret;
+       }
+
+       EXPECT_EQ(recv(self->cfd, buf, test_payload_size, MSG_WAITALL),
+                 test_payload_size);
+
+       close(fd);
+}
+
+TEST_F(tls, multi_chunk_sendfile)
+{
+       chunked_sendfile(_metadata, self, 4096, 4096);
+       chunked_sendfile(_metadata, self, 4096, 0);
+       chunked_sendfile(_metadata, self, 4096, 1);
+       chunked_sendfile(_metadata, self, 4096, 2048);
+       chunked_sendfile(_metadata, self, 8192, 2048);
+       chunked_sendfile(_metadata, self, 4096, 8192);
+       chunked_sendfile(_metadata, self, 8192, 4096);
+       chunked_sendfile(_metadata, self, 12288, 1024);
+       chunked_sendfile(_metadata, self, 12288, 2000);
+       chunked_sendfile(_metadata, self, 15360, 100);
+       chunked_sendfile(_metadata, self, 15360, 300);
+       chunked_sendfile(_metadata, self, 1, 4096);
+       chunked_sendfile(_metadata, self, 2048, 4096);
+       chunked_sendfile(_metadata, self, 2048, 8192);
+       chunked_sendfile(_metadata, self, 4096, 8192);
+       chunked_sendfile(_metadata, self, 1024, 12288);
+       chunked_sendfile(_metadata, self, 2000, 12288);
+       chunked_sendfile(_metadata, self, 100, 15360);
+       chunked_sendfile(_metadata, self, 300, 15360);
+}
+
 TEST_F(tls, recv_max)
 {
        unsigned int send_len = TLS_PAYLOAD_MAX_LEN;