Merge branch 'tls-honor-o_nonblock-in-tls_sw_splice_read'

Jakub Kicinski says:

====================
tls: Honor O_NONBLOCK in tls_sw_splice_read()

Extract the O_NONBLOCK fix from Chuck's zero-len record series:
https://lore.kernel.org/20261019-tls-follow-on-v6-0-ab01c4ecca0c@kernel.org

The first patch carries the fix. LLMs love to point out the missing
O_NONBLOCK as a risk for the zero-len record change so let's get
it out of the way before working on the zero-len record fix which
is more complex.

The fix itself is almost unchange (I deleted some parens),
the selftest was fixed up a little bit to appease the LLM
reviewers but also no substantial change.
====================

Link: https://patch.msgid.link/20261027015215.605919-1-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2026-10-28 16:50:24 -07:00
commit 4f43dff327
2 changed files with 37 additions and 3 deletions

View File

@ -2007,10 +2007,14 @@ ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos,
struct tls_msg *tlm;
struct sk_buff *skb;
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;
@ -2024,8 +2028,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,
true, false);
err = tls_rx_rec_wait(sk, nonblock, true, false);
if (err <= 0)
goto splice_read_end;

View File

@ -889,6 +889,37 @@ TEST_F(tls, splice_to_pipe)
EXPECT_EQ(memcmp(mem_send, mem_recv, send_len), 0);
}
/* The socket's O_NONBLOCK governs the record wait, as on a plain TCP
* socket, even without SPLICE_F_NONBLOCK.
*/
TEST_F(tls, splice_nonblock_socket)
{
struct pollfd pfd = { .fd = self->cfd, .events = POLLIN };
int send_len = TLS_PAYLOAD_MAX_LEN;
char mem_send[TLS_PAYLOAD_MAX_LEN];
char mem_recv[TLS_PAYLOAD_MAX_LEN];
int flags, p[2];
flags = fcntl(self->cfd, F_GETFL, 0);
ASSERT_GE(flags, 0);
ASSERT_EQ(fcntl(self->cfd, F_SETFL, flags | O_NONBLOCK), 0);
memrnd(mem_send, sizeof(mem_send));
ASSERT_GE(pipe(p), 0);
EXPECT_EQ(splice(self->cfd, NULL, p[1], NULL, send_len, 0), -1);
EXPECT_EQ(errno, EAGAIN);
/* The record may still be in flight, wait for it. A failed splice()
* would leave the read() below blocking until the harness timeout.
*/
EXPECT_EQ(send(self->fd, mem_send, send_len, 0), send_len);
ASSERT_EQ(poll(&pfd, 1, 5000), 1);
ASSERT_EQ(splice(self->cfd, NULL, p[1], NULL, send_len, 0), send_len);
EXPECT_EQ(read(p[0], mem_recv, send_len), send_len);
EXPECT_EQ(memcmp(mem_send, mem_recv, send_len), 0);
}
TEST_F(tls, splice_cmsg_to_pipe)
{
char *test_str = "test_read";