Author: rstone
Date: Thu Oct  4 22:03:58 2018
New Revision: 339185
URL: https://svnweb.freebsd.org/changeset/base/339185

Log:
  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)

Modified:
  head/sys/netinet/udp_usrreq.c

Modified: head/sys/netinet/udp_usrreq.c
==============================================================================
--- head/sys/netinet/udp_usrreq.c       Thu Oct  4 21:55:58 2018        
(r339184)
+++ head/sys/netinet/udp_usrreq.c       Thu Oct  4 22:03:58 2018        
(r339185)
@@ -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
        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,
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to