git: a7dcd4c2a9fb - stable/14 - tcp: improve segment validation in SYN-RECEIVED

From: Michael Tuexen <tuexen_at_FreeBSD.org>
Date: Sun, 05 Oct 2025 13:26:01 UTC
The branch stable/14 has been updated by tuexen:

URL: https://cgit.FreeBSD.org/src/commit/?id=a7dcd4c2a9fb35cac756db04326827efbaa4589b

commit a7dcd4c2a9fb35cac756db04326827efbaa4589b
Author:     Michael Tuexen <tuexen@FreeBSD.org>
AuthorDate: 2025-10-02 14:51:09 +0000
Commit:     Michael Tuexen <tuexen@FreeBSD.org>
CommitDate: 2025-10-05 13:25:35 +0000

    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
    Sponsored by:           Netflix, Inc.
    Differential Revision:  https://reviews.freebsd.org/D52849
    
    (cherry picked from commit b7118461f9099876cb2c2923948f8fb647defd57)
---
 sys/netinet/tcp_syncache.c | 32 +++++++++++++++++---------------
 1 file changed, 17 insertions(+), 15 deletions(-)

diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index 4ab0d251698c..ee3b9b4994c9 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -1265,19 +1265,6 @@ 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
@@ -1285,11 +1272,26 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
 		 */
 		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;
 		}