Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9fd2973

Browse files
q2vengregkh
authored andcommitted
tcp: Don't drop SYN+ACK for simultaneous connect().
[ Upstream commit 23e89e8 ] RFC 9293 states that in the case of simultaneous connect(), the connection gets established when SYN+ACK is received. [0] TCP Peer A TCP Peer B 1. CLOSED CLOSED 2. SYN-SENT --> <SEQ=100><CTL=SYN> ... 3. SYN-RECEIVED <-- <SEQ=300><CTL=SYN> <-- SYN-SENT 4. ... <SEQ=100><CTL=SYN> --> SYN-RECEIVED 5. SYN-RECEIVED --> <SEQ=100><ACK=301><CTL=SYN,ACK> ... 6. ESTABLISHED <-- <SEQ=300><ACK=101><CTL=SYN,ACK> <-- SYN-RECEIVED 7. ... <SEQ=100><ACK=301><CTL=SYN,ACK> --> ESTABLISHED However, since commit 0c24604 ("tcp: implement RFC 5961 4.2"), such a SYN+ACK is dropped in tcp_validate_incoming() and responded with Challenge ACK. For example, the write() syscall in the following packetdrill script fails with -EAGAIN, and wrong SNMP stats get incremented. 0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 +0 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress) +0 > S 0:0(0) <mss 1460,sackOK,TS val 1000 ecr 0,nop,wscale 8> +0 < S 0:0(0) win 1000 <mss 1000> +0 > S. 0:0(0) ack 1 <mss 1460,sackOK,TS val 3308134035 ecr 0,nop,wscale 8> +0 < S. 0:0(0) ack 1 win 1000 +0 write(3, ..., 100) = 100 +0 > P. 1:101(100) ack 1 -- # packetdrill cross-synack.pkt cross-synack.pkt:13: runtime error in write call: Expected result 100 but got -1 with errno 11 (Resource temporarily unavailable) # nstat ... TcpExtTCPChallengeACK 1 0.0 TcpExtTCPSYNChallenge 1 0.0 The problem is that bpf_skops_established() is triggered by the Challenge ACK instead of SYN+ACK. This causes the bpf prog to miss the chance to check if the peer supports a TCP option that is expected to be exchanged in SYN and SYN+ACK. Let's accept a bare SYN+ACK for active-open TCP_SYN_RECV sockets to avoid such a situation. Note that tcp_ack_snd_check() in tcp_rcv_state_process() is skipped not to send an unnecessary ACK, but this could be a bit risky for net.git, so this targets for net-next. Link: https://www.rfc-editor.org/rfc/rfc9293.html#section-3.5-7 [0] Signed-off-by: Kuniyuki Iwashima <[email protected]> Reviewed-by: Eric Dumazet <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 78c6e39 commit 9fd2973

File tree

1 file changed

+9
-0
lines changed

1 file changed

+9
-0
lines changed

net/ipv4/tcp_input.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5880,6 +5880,11 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
58805880
* RFC 5961 4.2 : Send a challenge ack
58815881
*/
58825882
if (th->syn) {
5883+
if (sk->sk_state == TCP_SYN_RECV && sk->sk_socket && th->ack &&
5884+
TCP_SKB_CB(skb)->seq + 1 == TCP_SKB_CB(skb)->end_seq &&
5885+
TCP_SKB_CB(skb)->seq + 1 == tp->rcv_nxt &&
5886+
TCP_SKB_CB(skb)->ack_seq == tp->snd_nxt)
5887+
goto pass;
58835888
syn_challenge:
58845889
if (syn_inerr)
58855890
TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS);
@@ -5889,6 +5894,7 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
58895894
goto discard;
58905895
}
58915896

5897+
pass:
58925898
bpf_skops_parse_hdr(sk, skb);
58935899

58945900
return true;
@@ -6673,6 +6679,9 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
66736679
tcp_fast_path_on(tp);
66746680
if (sk->sk_shutdown & SEND_SHUTDOWN)
66756681
tcp_shutdown(sk, SEND_SHUTDOWN);
6682+
6683+
if (sk->sk_socket)
6684+
goto consume;
66766685
break;
66776686

66786687
case TCP_FIN_WAIT1: {

0 commit comments

Comments
 (0)