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

[...]
> +             /* 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

Reply via email to