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@syzkaller.appspotmail.com
Reviewed by:		bz@, markj@
MFC after:		2 weeks
Sponsored by:		Netflix, Inc.
Differential Revision:	https://reviews.freebsd.org/D20936
This commit is contained in:
Michael Tuexen 2019-07-13 12:45:08 +00:00
parent d7143780ce
commit 9e44bc22d8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=349968

View file

@ -742,9 +742,24 @@ udp6_output(struct socket *so, int flags_arg, struct mbuf *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);