Linux Kernel Selftest development
 help / color / mirror / Atom feed
From: netdev-bot+sashiko@kernel.org
To: cel@kernel.org
Cc: john.fastabend@gmail.com, kuba@kernel.org, sd@queasysnail.net,
	davem@davemloft.net, pabeni@redhat.com, horms@kernel.org,
	davejwatson@fb.com, shuah@kernel.org, qingfang.deng@linux.dev,
	edumazet@kernel.org, netdev@vger.kernel.org,
	linux-kselftest@vger.kernel.org
Subject: Re: [PATCH net-next v2 6/8] selftests: tls: add peek and splice coverage for zero-length records
Date: Mon, 05 Oct 2026 23:22:27 +0000	[thread overview]
Message-ID: <179124254789.434549.2899145941558316898@kernel.org> (raw)
In-Reply-To: <20261001-tls-follow-on-v2-6-2dd1947bb642@kernel.org>

Thank you for your contribution! Sashiko AI review found more severe
issue(s) in other patches of this series. This mail is only an FYI, in case
you want to address the nit picks below when you respin.

Low priority / nit picks for your consideration:

- [Low] zero_len_peek in tools/testing/selftests/net/tls.c passes on a
  kernel that lacks the fix from commit "tls: consume empty data records…
- [Low] In TEST_F(zero_len_splice, test), the last check is commented
  "The empty records were consumed, not left queued".

--

selftests: tls: add peek and splice coverage for zero-length records

This adds two fixtures to tools/testing/selftests/net/tls.c,
zero_len_peek and zero_len_splice. They inject zero-length
application_data records over a socket that has only a TLS_RX key, then
exercise MSG_PEEK and splice() against them. The socket setup and record
sending code is moved into shared helpers used by all three zero_len
fixtures.

> diff --git a/tools/testing/selftests/net/tls.c b/tools/testing/selftests/net/tls.c
> index 9d3cd4fff062b..419c6cc0cc5e1 100644
> --- a/tools/testing/selftests/net/tls.c
> +++ b/tools/testing/selftests/net/tls.c

[ ... ]

> +/* Peeking past a run of empty data records must reach the payload
> + * behind them, and a run with no payload behind it must report EAGAIN
> + * rather than the zero return that means EOF.
> + */
> +TEST_F(zero_len_peek, test)
> +{
> +	const struct raw_rec *payload;
> +	unsigned char buf[128];
> +	ssize_t ret;
> +
> +	if (self->notls)
> +		SKIP(return, "no TLS support");
> +
> +	payload = zero_len_send_recs(_metadata, self->fd, variant->recs);
> +
> +	if (variant->peek_ret < 0) {
> +		ret = recv(self->cfd, buf, sizeof(buf),
> +			   MSG_DONTWAIT | MSG_PEEK);
> +		EXPECT_EQ(ret, -1);
> +		EXPECT_EQ(errno, -variant->peek_ret);
> +		return;
> +	}

[Severity: Low]
Can this test tell a fixed kernel from an unfixed one? It seems to pass on
a kernel without the "tls: consume empty data records in tls_sw_recvmsg()"
fix, which adds this branch in tls_sw_recvmsg():

net/tls/tls_sw.c:tls_sw_recvmsg() {
    ...
		if (!chunk && control == TLS_RECORD_TYPE_DATA) {
			if (!darg.zc)
				consume_skb(darg.skb);
    ...
}

Without that fix, the peek path queues each empty record on ctx->rx_list
via put_on_rx_list. In the 0data_0data_0data variant this leaves three
empty skbs on rx_list, and then tls_rx_rec_wait() returns -EAGAIN from:

	if (!timeo)
		return -EAGAIN;

That is the same -1/EAGAIN this branch expects. The comment above the test
contrasts EAGAIN with "the zero return that means EOF". Did the peek path
ever return 0 in this case?

The 0data_0data_data variant behaves the same way on both kernels. The peek
returns the 11-byte payload. On the next non-peek recv(), process_rx_list()
computes chunk as 0 for each empty skb:

	int chunk = min_t(unsigned int, rxm->full_len - skip, len);

so each one is unlinked and freed without any visible effect:

	if (!is_peek) {
		__skb_unlink(skb, &ctx->rx_list);
		consume_skb(skb);
	}

The commit message says:

    It reproduces no failure, because the unbounded rx_list growth needs a
    sustained flood that three fixed-sequence records cannot supply.

The retained records do appear to be visible with three records, though.
tls_sk_poll() in net/tls/tls_main.c reports readable while rx_list is
non-empty:

	if ((skb_queue_empty_lockless(&ctx->rx_list) &&
	     !tls_strp_msg_ready(ctx)) ||

Would a poll(cfd, POLLIN, 0) after the peek in the 0data_0data_0data
variant catch this? It should report readable on an unfixed kernel and not
readable on a fixed one.

[ ... ]

> +	} else {
> +		/* ASSERT so a zero return stops the test here; the read
> +		 * below would block until the harness timeout.
> +		 */
> +		ASSERT_EQ(splice(self->cfd, NULL, p[1], NULL, sizeof(buf),
> +				 SPLICE_F_NONBLOCK), variant->splice_ret);
> +		ret = read(p[0], buf, sizeof(buf));
> +		EXPECT_EQ(ret, variant->splice_ret);
> +		if (ret == variant->splice_ret)
> +			EXPECT_EQ(memcmp(buf, payload->plain_data,
> +					 variant->splice_ret), 0);
> +
> +		/* The empty records were consumed, not left queued */
> +		ret = recv(self->cfd, buf, sizeof(buf), MSG_DONTWAIT);
> +		EXPECT_EQ(ret, -1);
> +		EXPECT_EQ(errno, EAGAIN);

[Severity: Low]
Does this check prove what the comment says? It looks like recv() returns
-1/EAGAIN whether or not the empty records are still on ctx->rx_list.

If zero-length data skbs were still queued, recv() would go through
process_rx_list(). There, chunk is 0, so it copies nothing, frees each
empty skb and returns 0 without setting *more.

Back in tls_sw_recvmsg(), copied is 0, rx_more is false and control is
TLS_RECORD_TYPE_DATA, so it does not take this exit:

	if (len <= copied || rx_more ||
	    (control && control != TLS_RECORD_TYPE_DATA))
		goto end;

It then enters the receive loop, where tls_rx_rec_wait() returns -EAGAIN
for the non-blocking call.

The payload is the last record in every variant that reaches this branch,
so this assertion passes in both states. Should the comment be reworded, or
the check replaced with one that can see records left on rx_list, such as
the poll() check suggested above?

> +	}
> +
> +	close(p[0]);
> +	close(p[1]);
> +}

[ ... ]

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261001-tls-follow-on-v2-0-2dd1947bb642%40kernel.org

  reply	other threads:[~2026-10-05 23:22 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-01 22:41 [PATCH net-next v2 0/8] net/tls: Receive-path fixes for zero-length data records Chuck Lever
2026-10-01 22:41 ` [PATCH net-next v2 1/8] tls: bound consecutive no-data records in tls_sw_read_sock() Chuck Lever
2026-10-05 23:22   ` netdev-bot+sashiko
2026-10-06 15:44     ` Chuck Lever
2026-10-01 22:41 ` [PATCH net-next v2 2/8] tls: check for a pending signal after an empty record Chuck Lever
2026-10-05 23:22   ` netdev-bot+sashiko
2026-10-06 15:45     ` Chuck Lever
2026-10-01 22:41 ` [PATCH net-next v2 3/8] tls: consume empty data records in tls_sw_splice_read() Chuck Lever
2026-10-05 23:22   ` netdev-bot+sashiko
2026-10-06 15:45     ` Chuck Lever
2026-10-01 22:41 ` [PATCH net-next v2 4/8] tls: honor O_NONBLOCK " Chuck Lever
2026-10-05 23:22   ` netdev-bot+sashiko
2026-10-06 15:46     ` Chuck Lever
2026-10-01 22:41 ` [PATCH net-next v2 5/8] tls: consume empty data records in tls_sw_recvmsg() Chuck Lever
2026-10-05 23:22   ` netdev-bot+sashiko
2026-10-06 15:47     ` Chuck Lever
2026-10-01 22:41 ` [PATCH net-next v2 6/8] selftests: tls: add peek and splice coverage for zero-length records Chuck Lever
2026-10-05 23:22   ` netdev-bot+sashiko [this message]
2026-10-01 22:41 ` [PATCH net-next v2 7/8] selftests: tls: skip the zero_len tests when TLS is unavailable Chuck Lever
2026-10-05 23:22   ` netdev-bot+sashiko
2026-10-01 22:41 ` [PATCH net-next v2 8/8] selftests: tls: cover splice on a nonblocking socket Chuck Lever
2026-10-01 22:45 ` [PATCH net-next v2 0/8] net/tls: Receive-path fixes for zero-length data records netdev-bot+sinfo
2026-10-02 15:30   ` Chuck Lever
2026-10-04  6:36 ` Qingfang Deng

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=179124254789.434549.2899145941558316898@kernel.org \
    --to=netdev-bot+sashiko@kernel.org \
    --cc=cel@kernel.org \
    --cc=davejwatson@fb.com \
    --cc=davem@davemloft.net \
    --cc=edumazet@kernel.org \
    --cc=horms@kernel.org \
    --cc=john.fastabend@gmail.com \
    --cc=kuba@kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=qingfang.deng@linux.dev \
    --cc=sd@queasysnail.net \
    --cc=shuah@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox