Fix udp_output() lock inconsistency.
In r297225 the initial INP_RLOCK() was replaced by an early
acquisition of an r- or w-lock depending on input variables
possibly extending the write locked area for reasons not entirely
clear but possibly to avoid a later case of unlock and relock
leading to a possible race condition and possibly in order to
allow the route cache to work for connected sockets.
Unfortunately the conditions were not 1:1 replicated (probably
because of the route cache needs). While this would not be a
problem the legacy IP code compared to IPv6 has an extra case
when dealing with IP_SENDSRCADDR. In a particular case we were
holding an exclusive inp lock and acquired the shared udbinfo
lock (now epoch).
When then running into an error case, the locking assertions
on release fired as the udpinfo and inp lock levels did not match.
Break up the special case (and remove a lot of brackets to make
the other one more readable) and in that particular case acquire
and udpinfo lock depending on the exclusitivity of the inp lock.
While here avoid duplicate assignments of sin from addr after
r297225 and turn it into a KASSERT() making sure that our selection
argument does not get changed accidentally.
MFC After: 1 week
Reported-by: syzbot+1f5c6800e4f99bdb1a48@syzkaller.appspotmail.com
--
Original report can be found here:
https://groups.google.com/d/msg/syzkaller-freebsd-bugs/MHUQhKBFhHA/kBsbeOy-AwAJ