svn commit: r349968 - head/sys/netinet6

Michael Tuexen tuexen at FreeBSD.org
Sat Jul 13 12:45:10 UTC 2019


Author: tuexen
Date: Sat Jul 13 12:45:08 2019
New Revision: 349968
URL: https://svnweb.freebsd.org/changeset/base/349968

Log:
  r348494 fixes a race in udp_output(). The same race exists in
  udp_output6(), therefore apply a similar patch to IPv6.
  
  Reported by:		syzbot+c5ffbc8f14294c7b0e54 at syzkaller.appspotmail.com
  Reviewed by:		bz@, markj@
  MFC after:		2 weeks
  Sponsored by:		Netflix, Inc.
  Differential Revision:	https://reviews.freebsd.org/D20936

Modified:
  head/sys/netinet6/udp6_usrreq.c

Modified: head/sys/netinet6/udp6_usrreq.c
==============================================================================
--- head/sys/netinet6/udp6_usrreq.c	Sat Jul 13 10:46:01 2019	(r349967)
+++ head/sys/netinet6/udp6_usrreq.c	Sat Jul 13 12:45:08 2019	(r349968)
@@ -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-head mailing list