Hold a write lock across udp_notify()

With the new route cache feature udp_notify() will modify the inp when it
needs to invalidate the route cache.  Ensure that we hold a write lock on
the inp before calling the function to ensure that multiple threads don't
race while trying to invalidate the cache (which previously lead to a page
fault).

Differential Revision: https://reviews.freebsd.org/D17246
Reviewed by: sbruno, bz, karels
Sponsored by: Dell EMC Isilon
Approved by:	re (gjb)
This commit is contained in:
Ryan Stone 2018-10-04 22:03:58 +00:00
parent 8bff61a6ba
commit 083a010c62
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=339185

View File

@ -756,13 +756,7 @@ struct inpcb *
udp_notify(struct inpcb *inp, int errno)
{
/*
* While udp_ctlinput() always calls udp_notify() with a read lock
* when invoking it directly, in_pcbnotifyall() currently uses write
* locks due to sharing code with TCP. For now, accept either a read
* or a write lock, but a read lock is sufficient.
*/
INP_LOCK_ASSERT(inp);
INP_WLOCK_ASSERT(inp);
if ((errno == EHOSTUNREACH || errno == ENETUNREACH ||
errno == EHOSTDOWN) && inp->inp_route.ro_rt) {
RTFREE(inp->inp_route.ro_rt);
@ -808,13 +802,13 @@ udp_common_ctlinput(int cmd, struct sockaddr *sa, void *vip,
if (ip != NULL) {
uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
inp = in_pcblookup(pcbinfo, faddr, uh->uh_dport,
ip->ip_src, uh->uh_sport, INPLOOKUP_RLOCKPCB, NULL);
ip->ip_src, uh->uh_sport, INPLOOKUP_WLOCKPCB, NULL);
if (inp != NULL) {
INP_RLOCK_ASSERT(inp);
INP_WLOCK_ASSERT(inp);
if (inp->inp_socket != NULL) {
udp_notify(inp, inetctlerrmap[cmd]);
}
INP_RUNLOCK(inp);
INP_WUNLOCK(inp);
} else {
inp = in_pcblookup(pcbinfo, faddr, uh->uh_dport,
ip->ip_src, uh->uh_sport,