git: b712bb84a7a7 - main - tcp: fix TCPS_CLOSED state underleak in syncache_socket()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 07 Sep 2026 19:10:06 UTC
The branch main has been updated by glebius:
URL: https://cgit.FreeBSD.org/src/commit/?id=b712bb84a7a7dc229324a95170b8a77e0d9c5bec
commit b712bb84a7a7dc229324a95170b8a77e0d9c5bec
Author: Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2026-09-07 19:09:40 +0000
Commit: Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2026-09-07 19:09:40 +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
---
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 44288d8f344d..2320d6901fac 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -2455,7 +2455,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 33f62a73ce2c..ff046c7ad7de 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -209,6 +209,7 @@ tcp_usr_detach(struct socket *so)
tp->t_state < TCPS_SYN_SENT,
("%s: inp %p not disconnected or embryonic", __func__, inp));
+ TCPSTATES_DEC(tp->t_state);
tcp_discardcb(tp);
in_pcbfree(inp);
}