[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251016040159.3534435-4-kuniyu@google.com>
Date: Thu, 16 Oct 2025 04:00:35 +0000
From: Kuniyuki Iwashima <kuniyu@...gle.com>
To: Eric Dumazet <edumazet@...gle.com>, Neal Cardwell <ncardwell@...gle.com>,
"David S. Miller" <davem@...emloft.net>, Jakub Kicinski <kuba@...nel.org>, Paolo Abeni <pabeni@...hat.com>
Cc: Simon Horman <horms@...nel.org>, Yuchung Cheng <ycheng@...gle.com>,
Willem de Bruijn <willemb@...gle.com>, Kuniyuki Iwashima <kuniyu@...gle.com>,
Kuniyuki Iwashima <kuni1840@...il.com>, netdev@...r.kernel.org
Subject: [PATCH v1 net-next 3/4] tcp: Don't acknowledge SYN+ACK payload to TFO
fallback client.
Currently, SYN+ACK payload is acknowledged and queued even for a TFO
fallback client, which did not send SYN with payload.
For example, this packetdrill script does not fail, even though the
server does not send a TFO cookie.
0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3
+0 sendto(3, ..., 0, MSG_FASTOPEN, ..., ...) = -1 EINPROGRESS (Operation is now in progress)
+0 > S 0:0(0) <mss 1460,nop,nop,sackOK,nop,wscale 8,FO,nop,nop>
+0 < S. 0:1000(1000) ack 1 win 5840 <mss 1040,nop,nop,sackOK,nop,wscale 6>
+0 > . 1:1(0) ack 1001 // should be ack 1
+0 read(3, ..., 1000) = 1000 // should fail with -EAGAIN
This is because tcp_rcv_fastopen_synack(), which handles SYN+ACK for
both TFO client and TFO fallback client, calls tcp_fastopen_add_skb()
unconditionally.
RFC 7413 (TCP Fast Open), in Section 3. Protocol Overview [0], states
that the SYN+ACK payload is only allowed when the server acknowledges
SYN data:
3. If the server accepts the data in the SYN packet, it may send the
response data before the handshake finishes.
Let's not call tcp_fastopen_add_skb() when the client did not send
SYN with payload.
Note that Linux does not send SYN+ACK with payload but FreeBSD
could as mentioned in the commit below. [1]
Link: https://datatracker.ietf.org/doc/html/rfc7413#section-3 #[0]
Link: https://cgit.freebsd.org/src/commit/?id=3f43239f21e357246696f1e8675178881d9ed5bc #[1]
Fixes: 61d2bcae99f66 ("tcp: fastopen: accept data/FIN present in SYNACK message")
Signed-off-by: Kuniyuki Iwashima <kuniyu@...gle.com>
---
net/ipv4/tcp_input.c | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 8fc97f4d8a6b2..e1d3066782b57 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -6552,6 +6552,9 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
tcp_fastopen_cache_set(sk, mss, cookie, syn_drop, try_exp);
+ if (!tp->syn_data)
+ return false;
+
if (data) { /* Retransmit unacked data in SYN */
if (tp->total_retrans)
tp->fastopen_client_fail = TFO_SYN_RETRANSMITTED;
@@ -6564,16 +6567,14 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
LINUX_MIB_TCPFASTOPENACTIVEFAIL);
return true;
}
- tp->syn_data_acked = tp->syn_data;
- if (tp->syn_data_acked) {
- NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPFASTOPENACTIVE);
- /* SYN-data is counted as two separate packets in tcp_ack() */
- if (tp->delivered > 1)
- --tp->delivered;
- }
- tcp_fastopen_add_skb(sk, synack);
+ /* SYN-data is counted as two separate packets in tcp_ack() */
+ if (tp->delivered > 1)
+ --tp->delivered;
+ tp->syn_data_acked = 1;
+ tcp_fastopen_add_skb(sk, synack);
+ NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPFASTOPENACTIVE);
return false;
}
--
2.51.0.788.g6d19910ace-goog
Powered by blists - more mailing lists