Thread (29 messages) flat view 29 messages, 2 authors, 4d ago
COOLING4d

Revision v17 of 4 in this series.

Revisions (4)
  1. v14 [diff vs current]
  2. v15 [diff vs current]
  3. v16 [diff vs current]
  4. v17 current

[PATCH net-next v17 08/15] tcp: fence collapse against rtx-queue tail when write queue is empty

From: Rishikesh Jethwani <hidden>
Date: 2026-09-17 22:45:20
Subsystem: networking [general], networking [tcp], the rest · Maintainers: "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Neal Cardwell, Linus Torvalds

tcp_write_collapse_fence() marks the current write-queue tail as
end-of-record so a later tcp_retrans_try_collapse() / tcp_shift_skb_data()
does not merge across the fence. When nothing is queued for transmit the
write queue is empty, and the last skb of the current state is the
retransmit-queue tail (its end_seq == snd_nxt == write_seq); fence that
instead. Otherwise the boundary is left unmarked and a later collapse can
merge it with the first skb of the next state across the fence, since
those paths test only the tail's EOR, not skb->decrypted.

This is a critical fix for both TLS device offload and PSP (PSP Security
Protocol). Both use skb->decrypted to mark encrypted/transformed packets:
pre-key skbs stay decrypted=0, post-key skbs are decrypted=1. A collapse
can merge a post-key skb into a pre-key skb, whose decrypted=0 causes the
driver to send the post-key payload in cleartext.

The write-queue-empty case is the common state at the time encryption
keys are installed (tls_set_device_offload() setsockopt and
psp_sock_set_tx_key() in PSP), when the previous handshake or request
has just finished and nothing is being sent. The existing fence is a
no-op there (write_queue_tail is NULL), leaving the boundary unmarked.
A later retransmit of the final pre-key handshake record can then
collapse against new post-key data via tcp_retrans_try_collapse() or
SACK-driven tcp_shift_skb_data(), leaking the post-key payload in
cleartext.

This fix makes tcp_write_collapse_fence() fence the rtx-queue tail when
the write queue is empty, blocking the merge. TLS 1.3 device-offload
KeyUpdate additionally relies on this behavior to keep old-key and
new-key records in distinct skbs for re-encryption on RX.

Fixes: 1be68a87ab33 ("tcp: add a helper for setting EOR on tail skb")
Signed-off-by: Rishikesh Jethwani <redacted>
---
 include/net/tcp.h | 9 +++++++++
 1 file changed, 9 insertions(+)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 5e5f5f9b89a3..8c6d90e962c4 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -2340,6 +2340,15 @@ static inline void tcp_write_collapse_fence(struct sock *sk)
 {
 	struct sk_buff *skb = tcp_write_queue_tail(sk);
 
+	/* When nothing is queued for transmit, the last skb of the current
+	 * state is the rtx queue tail (its end_seq == snd_nxt == write_seq).
+	 * Fence that instead, otherwise the boundary is left unmarked and a
+	 * later tcp_retrans_try_collapse()/tcp_shift_skb_data() can merge it
+	 * with the first skb of the next state across the fence (they only test
+	 * the tail's EOR, not skb->decrypted).
+	 */
+	if (!skb)
+		skb = tcp_rtx_queue_tail(sk);
 	if (skb)
 		TCP_SKB_CB(skb)->eor = 1;
 }
-- 
2.50.1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help