Re: [PATCH net 5/9] net/tls: Consume empty data records in tls_sw_recvmsg()
flat view
From: Sabrina Dubroca <sd@queasysnail.net>
Date: 2026-07-30 12:40:05
Also in:
linux-kselftest
2026-07-26, 20:33:33 -0400, Chuck Lever wrote:
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
So we should just move the signal check to the top of tls_rx_rec_wait()'s loop? (just after all the existing error handling code) Then we don't need to add custom code everywhere, and we don't need to do that much special handling for 0-length records.
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.
[...]
quoted hunk ↗ jump to hunk
+ /* 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);
I don't see why you need this special handling. Could you explain that?
+ /* An empty record still marks a boundary. */ + msg->msg_flags |= MSG_EOR;
(note: I know that ship has sailed) I don't think the way ktls handles MSG_EOR on RX makes any sense, outside of non-DATA records. For non-DATA records, we only ever process one per call, so it works out. For DATA records, We set MSG_EOR when we process the end of a record, and then we process part of the next record. MSG_EOR is still set, eventhough we're not finishing the read at a record boundary. Userspace has no way of knowing where that record boundary was, or how many there may have been. -- Sabrina