aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Tuexen <tuexen@FreeBSD.org>2024-09-28 20:06:41 +0000
committerMichael Tuexen <tuexen@FreeBSD.org>2024-09-28 20:06:41 +0000
commitcbc9438f0505bd971e9eba635afdae38a267d76e (patch)
tree8e924a6ed84997a34262ae187fad484288481e19
parent37881f65eacd200b6aa31bcf75bdda089b83fbd5 (diff)
tcp: improve ref count handling when processing SYN
Don't leak a reference count for so->so_cred when processing an incoming SYN segment with an on-stack syncache entry and the sysctl variable net.inet.tcp.syncache.see_other is false. Reviewed by: cc, markj, rscheff MFC after: 1 week Sponsored by: Netflix, Inc. Pull Request: https://reviews.freebsd.org/D46793
-rw-r--r--sys/netinet/tcp_syncache.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index ed131421207d..19145446988e 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -1375,7 +1375,6 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
struct label *maclabel = NULL;
#endif
struct syncache scs;
- struct ucred *cred;
uint64_t tfo_response_cookie;
unsigned int *tfo_pending = NULL;
int tfo_cookie_valid = 0;
@@ -1392,7 +1391,6 @@ 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) {
@@ -1623,9 +1621,21 @@ skip_alloc:
#ifdef MAC
sc->sc_label = maclabel;
#endif
- sc->sc_cred = cred;
+ /*
+ * 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:
+ * - 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
+ sc->sc_cred = NULL;
sc->sc_port = port;
- cred = NULL;
sc->sc_ipopts = ipopts;
bcopy(inc, &sc->sc_inc, sizeof(struct in_conninfo));
sc->sc_ip_tos = ip_tos;
@@ -1761,8 +1771,6 @@ 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);