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 --- 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