Check through both recv() and splice() that a run of 128 empty data records is consumed and the data record behind it is delivered, and that a run of 129 breaks the connection with EBADMSG before the data record can be read. Two runs of 128 with a read returning EAGAIN in between must not break the connection, the cap applies to a burst the reader cannot keep up with, not to the connection as a whole. kTLS cannot send an empty record. A TLS 1.3 record of type 0 whose only byte is the data content type decrypts to one, since the receiver strips the 0 as padding. Signed-off-by: Jakub Kicinski --- tools/testing/selftests/net/tls.c | 124 ++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/tools/testing/selftests/net/tls.c b/tools/testing/selftests/net/tls.c index ed7feeac1cc4..48409f06a975 100644 --- a/tools/testing/selftests/net/tls.c +++ b/tools/testing/selftests/net/tls.c @@ -2889,6 +2889,130 @@ TEST_F(zero_len_splice, test) close(p[1]); } +FIXTURE(zero_len_run) +{ + int fd, cfd; + bool notls; +}; + +/* Before each of two reads, send n[i] empty records followed by a data + * record if data[i] is set. ret[i] is the result of the read. + */ +FIXTURE_VARIANT(zero_len_run) +{ + unsigned int n[2]; + bool data[2]; + int ret[2]; +}; + +FIXTURE_VARIANT_ADD(zero_len_run, 128) +{ + .n = { 128, 0, }, + .data = { true, false, }, + .ret = { 4, -EAGAIN, }, +}; + +/* More than 128 consecutive empty records break the connection */ +FIXTURE_VARIANT_ADD(zero_len_run, 129) +{ + .n = { 129, 0, }, + .data = { true, false, }, + .ret = { -EBADMSG, -EAGAIN, }, +}; + +/* The count starts over on every read */ +FIXTURE_VARIANT_ADD(zero_len_run, 128_128) +{ + .n = { 128, 128, }, + .data = { false, true, }, + .ret = { -EAGAIN, 4, }, +}; + +FIXTURE_SETUP(zero_len_run) +{ + struct tls_crypto_info_keys tls13; + int ret; + + tls_crypto_info_init(TLS_1_3_VERSION, TLS_CIPHER_AES_GCM_128, + &tls13, 0); + + ulp_sock_pair(_metadata, &self->fd, &self->cfd, &self->notls); + if (self->notls) + return; + + ret = setsockopt(self->fd, SOL_TLS, TLS_TX, &tls13, tls13.len); + ASSERT_EQ(ret, 0); + ret = setsockopt(self->cfd, SOL_TLS, TLS_RX, &tls13, tls13.len); + ASSERT_EQ(ret, 0); +} + +FIXTURE_TEARDOWN(zero_len_run) +{ + close(self->fd); + close(self->cfd); +} + +static void zero_len_run_send(struct __test_metadata *_metadata, int fd, + const FIXTURE_VARIANT(zero_len_run) *variant, + int i) +{ + /* kTLS cannot send an empty record. Send the data content type as + * the only byte of a record of type 0 instead, the receiver strips + * the 0 as padding and sees an empty data record. + */ + char data_type = 0x17; + unsigned int j; + + for (j = 0; j < variant->n[i]; j++) + ASSERT_EQ(tls_send_cmsg(fd, 0, &data_type, 1, 0), 1); + if (variant->data[i]) + ASSERT_EQ(send(fd, "data", 4, 0), 4); +} + +static void zero_len_run_expect(struct __test_metadata *_metadata, + ssize_t ret, int expected) +{ + EXPECT_EQ(ret, expected >= 0 ? expected : -1); + if (expected < 0) + EXPECT_EQ(errno, -expected); +} + +TEST_F(zero_len_run, recv) +{ + char buf[16]; + int i; + + if (self->notls) + SKIP(return, "no TLS support"); + + for (i = 0; i < 2; i++) { + zero_len_run_send(_metadata, self->fd, variant, i); + zero_len_run_expect(_metadata, + recv(self->cfd, buf, sizeof(buf), + MSG_DONTWAIT), + variant->ret[i]); + } +} + +TEST_F(zero_len_run, splice) +{ + int i, p[2]; + + if (self->notls) + SKIP(return, "no TLS support"); + + ASSERT_GE(pipe(p), 0); + for (i = 0; i < 2; i++) { + zero_len_run_send(_metadata, self->fd, variant, i); + zero_len_run_expect(_metadata, + splice(self->cfd, NULL, p[1], NULL, 16, + SPLICE_F_NONBLOCK), + variant->ret[i]); + } + close(p[0]); + close(p[1]); +} + FIXTURE(tls_err) { int fd, cfd; -- 2.56.0