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-all
mailing list