Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 28 Feb 2013 19:10:35 +0000
From:      Ed Maste <emaste@freebsd.org>
To:        freebsd-net@freebsd.org
Subject:   [PATCH] Handle PACKET_TAG_IPFORWARD and TIMEWAIT state
Message-ID:  <20130228191035.GA36576@sandvine.com>

next in thread | raw e-mail | index | archive | help

--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--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20130228191035.GA36576>