TLS 1.2 and TLS 1.3 both permit zero-length application_data records as a traffic-analysis countermeasure (RFC 5246, Section 6.2.1; RFC 8446, Section 5.1). Such a record decrypts to full_len == 0, so every arm of the receive loop reaches "decrypted += chunk" and "len -= chunk" with chunk == 0: len never reaches zero, and tls_strp_msg_ready() holds the second loop term true while the peer keeps records arriving. The peek arm and the async arm also queue each record on rx_list, which then grows without bound. tls_rx_rec_wait() returns without waiting whenever a record is already parsed, so its signal check never runs, and no other test in the loop consults signal_pending(). A peer streaming empty records therefore holds the caller in recvmsg(), unresponsive to SIGKILL, until it stops. Consume an empty data record as soon as the receive loop has it, before the paths diverge on darg.zc, and test for a pending signal there. Freeing the record's skb requires its decryption to have completed, so an empty record is no longer decrypted asynchronously, and the new branch sets MSG_EOR itself because the record no longer reaches the assignment at the bottom of the loop. Bytes already received take precedence over the signal: they are returned, and the signal is handled when the caller next enters the kernel. Fixes: c46234ebb4d1 ("tls: RX path for ktls") Signed-off-by: Chuck Lever --- net/tls/tls_sw.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c index f85d8a639731..0e76b31b1291 100644 --- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c @@ -1877,9 +1877,12 @@ int tls_sw_recvmsg(struct sock *sk, tlm->control == TLS_RECORD_TYPE_DATA) darg.zc = true; - /* Do not use async mode if record is non-data */ + /* Do not use async mode if record is non-data, or if it + * is empty: the receive loop frees an empty record's skb, + * so its decryption must have completed. + */ if (tlm->control == TLS_RECORD_TYPE_DATA) - darg.async = ctx->async_capable; + darg.async = ctx->async_capable && to_decrypt; else darg.async = false; @@ -1915,6 +1918,27 @@ int tls_sw_recvmsg(struct sock *sk, chunk = rxm->full_len; tls_rx_rec_done(ctx); + /* An empty record advances neither loop bound, so a flood + * of them can be interrupted only here. On the zero-copy + * path darg.skb is the strparser anchor, already released + * by tls_rx_rec_done(). + */ + if (tls_rx_empty_data_rec(chunk, control)) { + long timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); + + if (!darg.zc) + consume_skb(darg.skb); + + /* An empty record still marks a boundary. */ + msg->msg_flags |= MSG_EOR; + + if (signal_pending(current)) { + err = tls_rx_intr_errno(timeo); + goto recv_end; + } + continue; + } + if (!darg.zc) { bool partially_consumed = chunk > len; struct sk_buff *skb = darg.skb; -- 2.54.0