1

Merge branch 'tcp-make-simultaneous-connect-rfc-compliant'

Kuniyuki Iwashima says:

====================
tcp: Make simultaneous connect() RFC-compliant.

Patch 1 fixes an issue that BPF TCP option parser is triggered for ACK
instead of SYN+ACK in the case of simultaneous connect().

Patch 2 removes an wrong assumption in tcp_ao/self-connnect tests.

v2: https://lore.kernel.org/netdev/20240708180852.92919-1-kuniyu@amazon.com/
v1: https://lore.kernel.org/netdev/20240704035703.95065-1-kuniyu@amazon.com/
====================

Link: https://patch.msgid.link/20240710171246.87533-1-kuniyu@amazon.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2024-07-13 15:19:53 -07:00
commit 646d2ac752
2 changed files with 9 additions and 18 deletions

View File

@ -5998,6 +5998,11 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
* RFC 5961 4.2 : Send a challenge ack
*/
if (th->syn) {
if (sk->sk_state == TCP_SYN_RECV && sk->sk_socket && th->ack &&
TCP_SKB_CB(skb)->seq + 1 == TCP_SKB_CB(skb)->end_seq &&
TCP_SKB_CB(skb)->seq + 1 == tp->rcv_nxt &&
TCP_SKB_CB(skb)->ack_seq == tp->snd_nxt)
goto pass;
syn_challenge:
if (syn_inerr)
TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS);
@ -6007,6 +6012,7 @@ syn_challenge:
goto discard;
}
pass:
bpf_skops_parse_hdr(sk, skb);
return true;
@ -6813,6 +6819,9 @@ tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
tcp_fast_path_on(tp);
if (sk->sk_shutdown & SEND_SHUTDOWN)
tcp_shutdown(sk, SEND_SHUTDOWN);
if (sk->sk_socket)
goto consume;
break;
case TCP_FIN_WAIT1: {

View File

@ -30,8 +30,6 @@ static void setup_lo_intf(const char *lo_intf)
static void tcp_self_connect(const char *tst, unsigned int port,
bool different_keyids, bool check_restore)
{
uint64_t before_challenge_ack, after_challenge_ack;
uint64_t before_syn_challenge, after_syn_challenge;
struct tcp_ao_counters before_ao, after_ao;
uint64_t before_aogood, after_aogood;
struct netstat *ns_before, *ns_after;
@ -62,8 +60,6 @@ static void tcp_self_connect(const char *tst, unsigned int port,
ns_before = netstat_read();
before_aogood = netstat_get(ns_before, "TCPAOGood", NULL);
before_challenge_ack = netstat_get(ns_before, "TCPChallengeACK", NULL);
before_syn_challenge = netstat_get(ns_before, "TCPSYNChallenge", NULL);
if (test_get_tcp_ao_counters(sk, &before_ao))
test_error("test_get_tcp_ao_counters()");
@ -82,8 +78,6 @@ static void tcp_self_connect(const char *tst, unsigned int port,
ns_after = netstat_read();
after_aogood = netstat_get(ns_after, "TCPAOGood", NULL);
after_challenge_ack = netstat_get(ns_after, "TCPChallengeACK", NULL);
after_syn_challenge = netstat_get(ns_after, "TCPSYNChallenge", NULL);
if (test_get_tcp_ao_counters(sk, &after_ao))
test_error("test_get_tcp_ao_counters()");
if (!check_restore) {
@ -98,18 +92,6 @@ static void tcp_self_connect(const char *tst, unsigned int port,
close(sk);
return;
}
if (after_challenge_ack <= before_challenge_ack ||
after_syn_challenge <= before_syn_challenge) {
/*
* It's also meant to test simultaneous open, so check
* these counters as well.
*/
test_fail("%s: Didn't challenge SYN or ACK: %zu <= %zu OR %zu <= %zu",
tst, after_challenge_ack, before_challenge_ack,
after_syn_challenge, before_syn_challenge);
close(sk);
return;
}
if (test_tcp_ao_counters_cmp(tst, &before_ao, &after_ao, TEST_CNT_GOOD)) {
close(sk);