tcp: improve segment validation in SYN-RECEIVED

The validation of SEG.SEQ (first step in SEGMENT ARRIVES of RFC 9293)
should be done before the validation of SEG.ACK (fifth step in
SEGMENT ARRIVES in RFC 9293).
Furthermore, when the SEG.SEQ validation fails, a challenge ACK
should be sent instead of sending a RST-segment and moving the
endpoint to CLOSED.

Reported by:		Tilnel on freebsd-net
Reviewed by:		Nick Banks
MFC after:		3 days
Sponsored by:		Netflix, Inc.
Differential Revision:	https://reviews.freebsd.org/D52849
This commit is contained in:
Michael Tuexen
2025-10-02 16:51:09 +02:00
parent c23b64fba9
commit b7118461f9
+17 -15
View File
@@ -1258,6 +1258,23 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
}
}
/*
* SEG.SEQ validation:
* The SEG.SEQ must be in the window starting at our
* initial receive sequence number + 1.
*/
if (SEQ_LEQ(th->th_seq, sc->sc_irs) ||
SEQ_GT(th->th_seq, sc->sc_irs + sc->sc_wnd)) {
if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
log(LOG_DEBUG, "%s; %s: SEQ %u != IRS+1 %u, "
"sending challenge ACK\n",
s, __func__, th->th_seq, sc->sc_irs + 1);
syncache_send_challenge_ack(sc, m);
SCH_UNLOCK(sch);
free(s, M_TCPLOG);
return (-1); /* Do not send RST */;
}
/*
* SEG.ACK validation:
* SEG.ACK must match our initial send sequence number + 1.
@@ -1271,21 +1288,6 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
goto failed;
}
/*
* SEG.SEQ validation:
* The SEG.SEQ must be in the window starting at our
* initial receive sequence number + 1.
*/
if (SEQ_LEQ(th->th_seq, sc->sc_irs) ||
SEQ_GT(th->th_seq, sc->sc_irs + sc->sc_wnd)) {
SCH_UNLOCK(sch);
if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
log(LOG_DEBUG, "%s; %s: SEQ %u != IRS+1 %u, "
"segment rejected\n",
s, __func__, th->th_seq, sc->sc_irs + 1);
goto failed;
}
TAILQ_REMOVE(&sch->sch_bucket, sc, sc_hash);
sch->sch_length--;
#ifdef TCP_OFFLOAD