From nobody Wed Jun 17 13:56:33 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4ggQPs3wxjz6hP1S for ; Wed, 17 Jun 2026 13:56:33 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R13" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4ggQPs3CfMz3sjc for ; Wed, 17 Jun 2026 13:56:33 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1781704593; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=QeWCUZe4q1rD8fuIDgAFXfNW4bi7gabEoV2fd036EVY=; b=Dk0T2bkpAqyJFag38av+VO+5qDLrm/zPdc36ypAafTxyCB98bNSW1Y52l71pVDkbGA4g4c T2S7MjrWIe28Nb/3BizFrIjLYBJVFRNSMGaXpL28qE/lfQ7cG0braAgffxnFyBm1FeJZns xVrHbljIloTEuw18trWR5/MEGUj3RlwmX3mKqsX9uLuyjuasAjG//QJlp3cG43UNcBOc7O 3wkPzmb0wgkJT/FwGq4Ry+eU9Tis3ZP7NWVEqmI/9fo1r0Cn+1lTnyU0Tr5pB4LyRQU5lN Tt+YmCmtY79uZExRemqUolhO7DyhGEIC23yLnwW/uuOa1CY26Q0FND5iXqtzLg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1781704593; a=rsa-sha256; cv=none; b=jlTv2b/hoOn0H888AZ8AFmilNvrlnuOhfZkCH4qDJDL5LdyB3RIXKKGZq1IVq7LERMavTh Tepqb76Opoe7OBNYEKF74eSqUOXPfpNZtcERafFG3oPHAomnHcRpeOuMzu1Pl6ealVNHwo p9tH3PuO+XOD4yfyc9uJ1xfINpwllsgewFXTdD6y++sg9IwwYuqgLR+arrYsy1J4C5SplZ RXNvw8SBVD28VEpwQ8ZfqauQ3xI4s3JcUs/CWdkD/gpq0lsVwUUf0SWQe6PJ99QfSeOu9F vqbmItsFK1AU9/8DFfVaN47VLfruJsZ9ddlMbckn8gYYiM5ljOGpTJz4Om2Dkg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1781704593; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=QeWCUZe4q1rD8fuIDgAFXfNW4bi7gabEoV2fd036EVY=; b=iWc/MhquX2pnot+1WZoDusS5p6KJBh7TffrF5AWTW5XLqF2Fn7TTuqCtklb5KORhTvOowO qy5NSsTzWqORK/FRXpN5WiYaBLo0/Zdd3alBOaxnybNSkpEn1NpHIiPvKAhmWbrKHNjau/ HvDBcErge2ZFN8P8cNA+pq7OmL62t90axtN/qhpwr6kcdeN+no3KK/WwSdAjc+vWR2e2IJ IPHMCbVUfYht0oSDvWvRFyTFCNWoG/1T35px1AOtHzoIlOYWvRUFACQsGN86N7TmFL3Uc9 maWiooAt8ah0gqy9GTOFODfQZziCKvwMy59812McmJFKBw5bnCHfR/hQPcmIrw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4ggQPs2gMBzgY for ; Wed, 17 Jun 2026 13:56:33 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3864d by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Wed, 17 Jun 2026 13:56:33 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Michael Tuexen Subject: git: 1ed2bf1e0052 - main - tcp: cleanup resource handling in SYN handling List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: tuexen X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 1ed2bf1e0052df8dd6b429fc4ddd1908005f39ef Auto-Submitted: auto-generated Date: Wed, 17 Jun 2026 13:56:33 +0000 Message-Id: <6a32a791.3864d.76a27e68@gitrepo.freebsd.org> The branch main has been updated by tuexen: URL: https://cgit.FreeBSD.org/src/commit/?id=1ed2bf1e0052df8dd6b429fc4ddd1908005f39ef commit 1ed2bf1e0052df8dd6b429fc4ddd1908005f39ef Author: Michael Tuexen AuthorDate: 2026-06-17 13:46:56 +0000 Commit: Michael Tuexen CommitDate: 2026-06-17 13:46:56 +0000 tcp: cleanup resource handling in SYN handling Handle cred, ipopts, and maclabel using the same pattern: allocate at the beginning and set to NULL when the object is transferred to a struct syncache. When exiting the function, free these objects if not transferred or when transferred to the on-stack struct syncache. This makes use of a new function syncache_release(). This fixes a use after free problem: ipopts should only be freed, if the on-stack struct syncache is used and the pointer in this structure still points to the allocated ipopts. If the ipopts are moved from the struct syncache to the struct inpcb in syncache_socket(), which is called by syncache_tfo_expand(), the pointer in the struct syncache is set to NULL. In a FreeBSD default setup this problem is mitigated by 1. TCP fast open support on the server side not being enabled (the sysctl-variable net.inet.tcp.fastopen.server_enable is 0). 2. Incoming IP packet with source routing options are not being processed by the host stack (the sysctl-variable net.inet.ip.accept_sourceroute is 0). Only if these two sysctl-variables are changed, a FreeBSD system is affected, if a server actually using TCP fast open is running. Reported by: Yuxiang Yang, Yizhou Zhao, Xuewei Feng, Qi Li, and Ke Xu from Tsinghua University using GLM5.1 from Z.ai Reviewed by: markj, rscheff MFC after: 3 days Sponsored by: Netflix, Inc. Differential Revision: https://reviews.freebsd.org/D57374 --- sys/netinet/tcp_syncache.c | 70 +++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 42 deletions(-) diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index 22f260db9805..0d8f725455b7 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -224,21 +224,25 @@ static MALLOC_DEFINE(M_SYNCACHE, "syncache", "TCP syncache"); #define SCH_UNLOCK(sch) mtx_unlock(&(sch)->sch_mtx) #define SCH_LOCK_ASSERT(sch) mtx_assert(&(sch)->sch_mtx, MA_OWNED) -/* - * Requires the syncache entry to be already removed from the bucket list. - */ static void -syncache_free(struct syncache *sc) +syncache_release(struct syncache *sc) { - - if (sc->sc_ipopts) + if (sc->sc_ipopts != NULL) (void)m_free(sc->sc_ipopts); - if (sc->sc_cred) + if (sc->sc_cred != NULL) crfree(sc->sc_cred); #ifdef MAC mac_syncache_destroy(&sc->sc_label); #endif +} +/* + * Requires the syncache entry to be already removed from the bucket list. + */ +static void +syncache_free(struct syncache *sc) +{ + syncache_release(sc); uma_zfree(V_tcp_syncache.zone, sc); } @@ -1427,6 +1431,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); + bzero(&scs, sizeof(scs)); cred = V_tcp_syncache.see_other ? NULL : crhold(so->so_cred); #ifdef INET6 @@ -1551,14 +1556,15 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, if (tfo_cookie_valid) INP_RUNLOCK(inp); TCPSTAT_INC(tcps_sc_dupsyn); - if (ipopts) { + if (ipopts != NULL) { /* * If we were remembering a previous source route, * forget it and use the new one we've been given. */ - if (sc->sc_ipopts) + if (sc->sc_ipopts != NULL) (void)m_free(sc->sc_ipopts); sc->sc_ipopts = ipopts; + ipopts = NULL; } /* * Update timestamp if present. @@ -1575,14 +1581,6 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, sc->sc_flags &= ~SCF_ECN_MASK; sc->sc_flags |= tcp_ecn_syncache_add(tcp_get_flags(th), iptos); } -#ifdef MAC - /* - * Since we have already unconditionally allocated label - * storage, free it up. The syncache entry will already - * have an initialized label we can use. - */ - mac_syncache_destroy(&maclabel); -#endif TCP_PROBE5(receive, NULL, NULL, m, NULL, th); /* Retransmit SYN|ACK and reset retransmit count. */ if ((s = tcp_log_addrs(&sc->sc_inc, th, NULL, NULL))) { @@ -1613,10 +1611,9 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, * Skip allocating a syncache entry if we are just going to discard * it later. */ - if (!locked || tfo_cookie_valid) { - bzero(&scs, sizeof(scs)); + if (!locked || tfo_cookie_valid) sc = &scs; - } else { + else { sc = uma_zalloc(V_tcp_syncache.zone, M_NOWAIT | M_ZERO); if (sc == NULL) { /* @@ -1633,10 +1630,9 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, } sc = uma_zalloc(V_tcp_syncache.zone, M_NOWAIT | M_ZERO); if (sc == NULL) { - if (V_tcp_syncookies) { - bzero(&scs, sizeof(scs)); + if (V_tcp_syncookies) sc = &scs; - } else { + else { KASSERT(locked, ("%s: bucket unexpectedly unlocked", __func__)); @@ -1656,23 +1652,13 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, */ #ifdef MAC sc->sc_label = maclabel; + maclabel = NULL; #endif - /* - * 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 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 = cred; - cred = NULL; - } else - sc->sc_cred = NULL; - sc->sc_port = port; + sc->sc_cred = cred; + cred = NULL; sc->sc_ipopts = ipopts; + ipopts = NULL; + sc->sc_port = port; bcopy(inc, &sc->sc_inc, sizeof(struct in_conninfo)); sc->sc_ip_tos = ip_tos; sc->sc_ip_ttl = ip_ttl; @@ -1819,13 +1805,13 @@ donenoprobe: tfo_expanded: if (cred != NULL) crfree(cred); - if (sc == NULL || sc == &scs) { #ifdef MAC + if (maclabel != NULL) mac_syncache_destroy(&maclabel); #endif - if (ipopts) - (void)m_free(ipopts); - } + if (ipopts != NULL) + (void)m_free(ipopts); + syncache_release(&scs); return (rv); }