From: Chuck Lever <cel@kernel.org>
To: John Fastabend <john.fastabend@gmail.com>,
Jakub Kicinski <kuba@kernel.org>,
Sabrina Dubroca <sd@queasysnail.net>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Paolo Abeni <pabeni@redhat.com>, Simon Horman <horms@kernel.org>,
Chuck Lever <cel@kernel.org>, Dave Watson <davejwatson@fb.com>,
Shuah Khan <shuah@kernel.org>
Cc: netdev@vger.kernel.org, linux-kselftest@vger.kernel.org
Subject: [PATCH net 4/9] net/tls: Honor O_NONBLOCK in tls_sw_splice_read()
Date: Sun, 26 Jul 2026 20:33:32 -0400 [thread overview]
Message-ID: <20260726-tls-follow-on-v1-4-99bf4cc1c729@kernel.org> (raw)
In-Reply-To: <20260726-tls-follow-on-v1-0-99bf4cc1c729@kernel.org>
tls_sw_splice_read() currently derives its blocking behavior from
SPLICE_F_NONBLOCK alone; the socket's own O_NONBLOCK is invisible
to it. A splice(2) call without SPLICE_F_NONBLOCK on a nonblocking
socket therefore sleeps in tls_rx_rec_wait() until a record
arrives, where tcp_splice_read() reads sock->file->f_flags and
returns -EAGAIN.
The sleep is reachable through poll. tls_sw_sock_is_readable()
reports a socket readable while any record sits on rx_list,
including a zero-length data record that delivers no bytes to the
pipe. The splice path consumes it and waits for the next one. The
readiness test cannot screen such a record out, since the strparser
announces a record before decryption, when the plaintext length is
not yet known. An event loop that polls, then splices, stalls on
that connection and starves every other one it multiplexes.
Note that a caller that sets O_NONBLOCK and then splices without
SPLICE_F_NONBLOCK, taking that flag to govern only the pipe, now
gets -EAGAIN where it previously blocked. sendfile(2) from a TLS
socket changes the same way, because do_sendfile() leaves the input
file's O_NONBLOCK out of the splice flags. Both then behave as they
do on a plain TCP socket.
Fixes: c46234ebb4d1 ("tls: RX path for ktls")
Signed-off-by: Chuck Lever <cel@kernel.org>
---
net/tls/tls_sw.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 99e9a9aa995c..f85d8a639731 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -2011,10 +2011,14 @@ ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos,
struct sk_buff *skb;
bool released = true;
ssize_t copied = 0;
+ bool nonblock;
int chunk;
int err;
- err = tls_rx_reader_lock(sk, ctx, flags & SPLICE_F_NONBLOCK);
+ nonblock = (flags & SPLICE_F_NONBLOCK) ||
+ (sock->file->f_flags & O_NONBLOCK);
+
+ err = tls_rx_reader_lock(sk, ctx, nonblock);
if (err < 0)
return err;
@@ -2029,8 +2033,7 @@ ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos,
} else {
struct tls_decrypt_arg darg;
- err = tls_rx_rec_wait(sk, flags & SPLICE_F_NONBLOCK,
- released, false);
+ err = tls_rx_rec_wait(sk, nonblock, released, false);
if (err <= 0)
goto splice_read_end;
@@ -2063,7 +2066,7 @@ ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos,
* while a record is parsed, so test for a signal here.
*/
if (tls_rx_empty_data_rec(rxm->full_len, tlm->control)) {
- long timeo = sock_rcvtimeo(sk, flags & SPLICE_F_NONBLOCK);
+ long timeo = sock_rcvtimeo(sk, nonblock);
consume_skb(skb);
if (signal_pending(current)) {
--
2.54.0
next prev parent reply other threads:[~2026-07-27 0:33 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-27 0:33 [PATCH net 0/9] net/tls: Receive-path fixes for zero-length data records Chuck Lever
2026-07-27 0:33 ` [PATCH net 1/9] net/tls: Bound time spent on no-data records in tls_sw_read_sock() Chuck Lever
2026-07-27 0:33 ` [PATCH net 2/9] net/tls: Consume empty data records in tls_sw_splice_read() Chuck Lever
2026-07-27 0:33 ` [PATCH net 3/9] net/tls: Fail tls_sw_splice_read() after a failed async decrypt Chuck Lever
2026-07-27 0:33 ` Chuck Lever [this message]
2026-07-27 0:33 ` [PATCH net 5/9] net/tls: Consume empty data records in tls_sw_recvmsg() Chuck Lever
2026-07-27 0:33 ` [PATCH net 6/9] selftests: tls: add peek and splice coverage for zero-length records Chuck Lever
2026-07-27 14:07 ` Sabrina Dubroca
2026-07-27 0:33 ` [PATCH net 7/9] selftests: tls: skip the zero_len tests when TLS is unavailable Chuck Lever
2026-07-27 0:33 ` [PATCH net 8/9] selftests: tls: cover splice on a nonblocking socket Chuck Lever
2026-07-27 0:33 ` [PATCH net 9/9] selftests: tls: cover splice after a failed decrypt Chuck Lever
2026-07-27 15:19 ` Sabrina Dubroca
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=20260726-tls-follow-on-v1-4-99bf4cc1c729@kernel.org \
--to=cel@kernel.org \
--cc=davejwatson@fb.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--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=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