svn commit: r351971 - stable/12/sys/netinet6

Michael Tuexen tuexen at FreeBSD.org
Sat Sep 7 10:45:45 UTC 2019


Author: tuexen
Date: Sat Sep  7 10:45:44 2019
New Revision: 351971
URL: https://svnweb.freebsd.org/changeset/base/351971

Log:
  MFC r349968:
  
  r348494 fixes a race in udp_output(). The same race exists in
  udp_output6(), therefore apply a similar patch to IPv6.
  
  Reviewed by:		bz@, markj@
  Differential Revision:	https://reviews.freebsd.org/D20936

Modified:
  stable/12/sys/netinet6/udp6_usrreq.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/netinet6/udp6_usrreq.c
==============================================================================
--- stable/12/sys/netinet6/udp6_usrreq.c	Sat Sep  7 10:39:49 2019	(r351970)
+++ stable/12/sys/netinet6/udp6_usrreq.c	Sat Sep  7 10:45:44 2019	(r351971)
@@ -742,9 +742,24 @@ udp6_output(struct socket *so, int flags_arg, struct m
 	 * - when we are not bound to an address and source port (it is
 	 *   in6_pcbsetport() which will require the write lock).
 	 */
+retry:
 	if (sin6 == NULL || (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) &&
 	    inp->inp_lport == 0)) {
 		INP_WLOCK(inp);
+		/*
+		 * In case we lost a race and another thread bound addr/port
+		 * on the inp we cannot keep the wlock (which still would be
+		 * fine) as further down, based on these values we make
+		 * decisions for the pcbinfo lock.  If the locks are not in
+		 * synch the assertions on unlock will fire, hence we go for
+		 * one retry loop.
+		 */
+		if (sin6 != NULL &&
+		    (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) ||
+		    inp->inp_lport != 0)) {
+			INP_WUNLOCK(inp);
+			goto retry;
+		}
 		unlock_inp = UH_WLOCKED;
 	} else {
 		INP_RLOCK(inp);


More information about the svn-src-stable-12 mailing list