aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Tuexen <tuexen@FreeBSD.org>2025-10-02 14:51:09 +0000
committerMichael Tuexen <tuexen@FreeBSD.org>2025-10-02 14:51:09 +0000
commitb7118461f9099876cb2c2923948f8fb647defd57 (patch)
treed93638a8c7caf9d5217e71d0dee47abc2545cff9
parentc23b64fba9fb9715397a9e6ecbae670ee791dce9 (diff)
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
-rw-r--r--sys/netinet/tcp_syncache.c32
1 files changed, 17 insertions, 15 deletions
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index 778ab0583735..7f842512858d 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -1259,30 +1259,32 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
}
/*
- * SEG.ACK validation:
- * SEG.ACK must match our initial send sequence number + 1.
- */
- if (th->th_ack != sc->sc_iss + 1) {
- SCH_UNLOCK(sch);
- if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
- log(LOG_DEBUG, "%s; %s: ACK %u != ISS+1 %u, "
- "segment rejected\n",
- s, __func__, th->th_ack, sc->sc_iss + 1);
- 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",
+ "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.
+ */
+ if (th->th_ack != sc->sc_iss + 1) {
+ SCH_UNLOCK(sch);
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
+ log(LOG_DEBUG, "%s; %s: ACK %u != ISS+1 %u, "
+ "segment rejected\n",
+ s, __func__, th->th_ack, sc->sc_iss + 1);
goto failed;
}