From owner-freebsd-net@FreeBSD.ORG Thu Feb 28 19:10:36 2013 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 385A817C for ; Thu, 28 Feb 2013 19:10:36 +0000 (UTC) (envelope-from emaste@freebsd.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:1900:2254:206c::16:87]) by mx1.freebsd.org (Postfix) with ESMTP id 27CB1D38 for ; Thu, 28 Feb 2013 19:10:36 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.6/8.14.6) with ESMTP id r1SJAaeh038529 for ; Thu, 28 Feb 2013 19:10:36 GMT (envelope-from emaste@freebsd.org) Received: (from emaste@localhost) by freefall.freebsd.org (8.14.6/8.14.6/Submit) id r1SJAZPe038528 for freebsd-net@freebsd.org; Thu, 28 Feb 2013 19:10:35 GMT (envelope-from emaste@freebsd.org) X-Authentication-Warning: freefall.freebsd.org: emaste set sender to emaste@freebsd.org using -f Date: Thu, 28 Feb 2013 19:10:35 +0000 From: Ed Maste To: freebsd-net@freebsd.org Subject: [PATCH] Handle PACKET_TAG_IPFORWARD and TIMEWAIT state Message-ID: <20130228191035.GA36576@sandvine.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="VbJkn9YxBvnuCH5J" Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 28 Feb 2013 19:10:36 -0000 --VbJkn9YxBvnuCH5J Content-Type: text/plain; charset=us-ascii Content-Disposition: inline SVN rev 244157 introduced a fix for a crash in tcp_input() which would occur in the case of a packet with a PACKET_TAG_IPFORWARD m_tag arriving for a flow in TIMEWAIT. Such packets resulted in a goto findpcb an a double free of the m_tag. Unfortunately the fix causes the fwd_tag to be lost for any subsequent trips through the pcb lookup code. The attached patch keeps the fwd_tag around until finished with pcb lookup. The #ifdef INET / INET6 is a bit torturous, but no worse than what was there. --VbJkn9YxBvnuCH5J Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="fwd_tag_findpcb.diff" Index: tcp_input.c =================================================================== --- tcp_input.c (revision 247398) +++ tcp_input.c (working copy) @@ -768,6 +768,28 @@ } else ti_locked = TI_UNLOCKED; + /* + * Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain. + */ +#ifdef INET6 + if (isipv6 && (m->m_flags & M_IP6_NEXTHOP)) { + m->m_flags &= ~M_IP6_NEXTHOP; + fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL); + m_tag_unlink(m, fwd_tag); + } +#ifdef INET + else if (!isipv6 && (m->m_flags & M_IP_NEXTHOP)) { +#endif +#elif defined(INET) + if (m->m_flags & M_IP_NEXTHOP) { +#endif +#if defined(INET) + m->m_flags &= ~M_IP_NEXTHOP; + fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL); + m_tag_unlink(m, fwd_tag); + } +#endif + findpcb: #ifdef INVARIANTS if (ti_locked == TI_WLOCKED) { @@ -777,23 +799,7 @@ } #endif - /* - * Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain. - */ - if ( #ifdef INET6 - (isipv6 && (m->m_flags & M_IP6_NEXTHOP)) -#ifdef INET - || (!isipv6 && (m->m_flags & M_IP_NEXTHOP)) -#endif -#endif -#if defined(INET) && !defined(INET6) - (m->m_flags & M_IP_NEXTHOP) -#endif - ) - fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL); - -#ifdef INET6 if (isipv6 && fwd_tag != NULL) { struct sockaddr_in6 *next_hop6; @@ -817,10 +823,6 @@ th->th_dport, INPLOOKUP_WILDCARD | INPLOOKUP_WLOCKPCB, m->m_pkthdr.rcvif); } - /* Remove the tag from the packet. We don't need it anymore. */ - m_tag_delete(m, fwd_tag); - m->m_flags &= ~M_IP6_NEXTHOP; - fwd_tag = NULL; } else if (isipv6) { inp = in6_pcblookup_mbuf(&V_tcbinfo, &ip6->ip6_src, th->th_sport, &ip6->ip6_dst, th->th_dport, @@ -855,10 +857,6 @@ th->th_dport, INPLOOKUP_WILDCARD | INPLOOKUP_WLOCKPCB, m->m_pkthdr.rcvif); } - /* Remove the tag from the packet. We don't need it anymore. */ - m_tag_delete(m, fwd_tag); - m->m_flags &= ~M_IP_NEXTHOP; - fwd_tag = NULL; } else inp = in_pcblookup_mbuf(&V_tcbinfo, ip->ip_src, th->th_sport, ip->ip_dst, th->th_dport, @@ -970,6 +968,8 @@ if (tcp_twcheck(inp, &to, th, m, tlen)) goto findpcb; INP_INFO_WUNLOCK(&V_tcbinfo); + if (fwd_tag != NULL) + m_tag_free(fwd_tag); return; } /* @@ -1020,6 +1020,10 @@ } INP_INFO_WLOCK_ASSERT(&V_tcbinfo); } + if (fwd_tag) { + m_tag_free(fwd_tag); + fwd_tag = NULL; + } #ifdef MAC INP_WLOCK_ASSERT(inp); @@ -1429,6 +1433,8 @@ drop: INP_INFO_UNLOCK_ASSERT(&V_tcbinfo); + if (fwd_tag != NULL) + m_tag_free(fwd_tag); if (s != NULL) free(s, M_TCPLOG); if (m != NULL) --VbJkn9YxBvnuCH5J--