Thread (29 messages) 29 messages, 3 authors, 2026-08-07

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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help