git: 4b555b56edfd - stable/14 - tcp: improve credential handling in syncache
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 31 Oct 2025 19:14:44 UTC
The branch stable/14 has been updated by tuexen:
URL: https://cgit.FreeBSD.org/src/commit/?id=4b555b56edfdd714df9010bbbb630d3d3a32f6d0
commit 4b555b56edfdd714df9010bbbb630d3d3a32f6d0
Author: Michael Tuexen <tuexen@FreeBSD.org>
AuthorDate: 2025-10-27 22:28:59 +0000
Commit: Michael Tuexen <tuexen@FreeBSD.org>
CommitDate: 2025-10-31 14:14:10 +0000
tcp: improve credential handling in syncache
When adding a syncache entry, take a reference count of the
credentials while the inp is still locked.
Thanks to markj@ for providing a hint regarding the root cause.
Reported by: David Marker
Reviewed by: glebius
Tested by: David Marker
Fixes: cbc9438f0505 ("tcp: improve ref count handling when processing SYN")
Sponsored by: Netflix, Inc.
Differential Revision: https://reviews.freebsd.org/D53380
(cherry picked from commit 44cb1e857f048d2326bdc1a032ccd2c04d2bcdc9)
---
sys/netinet/tcp_syncache.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index f1402734103a..713f6a35ad45 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -1387,6 +1387,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
struct tcpcb *tp;
struct socket *rv = NULL;
struct syncache *sc = NULL;
+ struct ucred *cred;
struct syncache_head *sch;
struct mbuf *ipopts = NULL;
u_int ltflags;
@@ -1415,6 +1416,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
*/
KASSERT(SOLISTENING(so), ("%s: %p not listening", __func__, so));
tp = sototcpcb(so);
+ cred = V_tcp_syncache.see_other ? NULL : crhold(so->so_cred);
#ifdef INET6
if (inc->inc_flags & INC_ISIPV6) {
@@ -1643,16 +1645,16 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
/*
* sc_cred is only used in syncache_pcblist() to list TCP endpoints in
* TCPS_SYN_RECEIVED state when V_tcp_syncache.see_other is false.
- * Therefore, store the credentials and take a reference count only
- * when needed:
+ * Therefore, store the credentials only when needed:
* - sc is allocated from the zone and not using the on stack instance.
* - the sysctl variable net.inet.tcp.syncache.see_other is false.
* The reference count is decremented when a zone allocated sc is
* freed in syncache_free().
*/
- if (sc != &scs && !V_tcp_syncache.see_other)
- sc->sc_cred = crhold(so->so_cred);
- else
+ if (sc != &scs && !V_tcp_syncache.see_other) {
+ sc->sc_cred = cred;
+ cred = NULL;
+ } else
sc->sc_cred = NULL;
sc->sc_port = port;
sc->sc_ipopts = ipopts;
@@ -1790,6 +1792,8 @@ donenoprobe:
tcp_fastopen_decrement_counter(tfo_pending);
tfo_expanded:
+ if (cred != NULL)
+ crfree(cred);
if (sc == NULL || sc == &scs) {
#ifdef MAC
mac_syncache_destroy(&maclabel);