git: 7b4bc013b179 - stable/15 - tcp: fix TCPS_CLOSED state underleak in syncache_socket()

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Thu, 24 Sep 2026 03:33:33 UTC
The branch stable/15 has been updated by glebius:

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

commit 7b4bc013b179ab067e9c6212279078b24c11c60c
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2026-09-07 19:09:40 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2026-09-24 03:32:49 +0000

    tcp: fix TCPS_CLOSED state underleak in syncache_socket()
    
    The syncache entry holds one TCPS_SYN_RECEIVED count that normally is
    transferred to the the newborn tp.  Upon failure syncache_socket() shall
    not use TCPSTATES_INC/TCPSTATES_DEC (see 5050df3f4aa4 why).  But when
    syncache_socket() fails in_pcbconnect(), it calls tcp_discardcb() to free
    resources that were just allocated by tcp_newtcpcb() and this
    tcp_discardcb() would do TCPSTATES_DEC(tp->t_state).  The t_state is
    TCPS_CLOSED at this point.
    
    Make tcp_discardcb() symmetrical to tcp_newtcpcb() - not responsible for
    the TCPSTATES.  Make the caller responsible for state count book keeping.
    
    Reviewed by:            tuexen
    Fixes:                  3703e1a73e0e0367c04f47f793e46495e46e647b
    Differential Revision:  https://reviews.freebsd.org/D59325
    
    (cherry picked from commit b712bb84a7a7dc229324a95170b8a77e0d9c5bec)
---
 sys/netinet/tcp_subr.c   | 1 -
 sys/netinet/tcp_usrreq.c | 1 +
 2 files changed, 1 insertion(+), 1 deletion(-)

diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index d8e58fe3eff1..663042cd8c93 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -2447,7 +2447,6 @@ tcp_discardcb(struct tcpcb *tp)
 		STAILQ_FOREACH_FROM_SAFE(m, &tp->t_inqueue, m_stailqpkt, prev)
 			m_freem(m);
 	}
-	TCPSTATES_DEC(tp->t_state);
 
 	if (tp->t_fb->tfb_tcp_fb_fini)
 		(*tp->t_fb->tfb_tcp_fb_fini)(tp, 1);
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 4d1a6455d09e..6b2388b9363c 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -208,6 +208,7 @@ tcp_usr_detach(struct socket *so)
 	    tp->t_state < TCPS_SYN_SENT,
 	    ("%s: inp %p not dropped or embryonic", __func__, inp));
 
+	TCPSTATES_DEC(tp->t_state);
 	tcp_discardcb(tp);
 	in_pcbfree(inp);
 }