Author: ae
Date: Tue Jun 13 10:52:31 2017
New Revision: 319895
URL: https://svnweb.freebsd.org/changeset/base/319895

Log:
  Resurrect RTF_RNH_LOCKED flag and restore ability to call rtalloc1_fib()
  with acquired RIB lock.
  
  This fixes a possible panic due to trying to acquire RIB rlock when it is
  already exclusive locked.
  
  PR:           215963, 215122
  MFC after:    1 week
  Sponsored by: Yandex LLC

Modified:
  head/sys/net/route.c
  head/sys/net/route.h

Modified: head/sys/net/route.c
==============================================================================
--- head/sys/net/route.c        Tue Jun 13 10:38:28 2017        (r319894)
+++ head/sys/net/route.c        Tue Jun 13 10:52:31 2017        (r319895)
@@ -454,18 +454,23 @@ rtalloc1_fib(struct sockaddr *dst, int report, u_long 
        /*
         * Look up the address in the table for that Address Family
         */
-       RIB_RLOCK(rh);
+       if ((ignflags & RTF_RNH_LOCKED) == 0)
+               RIB_RLOCK(rh);
+#ifdef INVARIANTS
+       else
+               RIB_LOCK_ASSERT(rh);
+#endif
        rn = rh->rnh_matchaddr(dst, &rh->head);
        if (rn && ((rn->rn_flags & RNF_ROOT) == 0)) {
                newrt = RNTORT(rn);
                RT_LOCK(newrt);
                RT_ADDREF(newrt);
-               RIB_RUNLOCK(rh);
+               if ((ignflags & RTF_RNH_LOCKED) == 0)
+                       RIB_RUNLOCK(rh);
                return (newrt);
 
-       } else
+       } else if ((ignflags & RTF_RNH_LOCKED) == 0)
                RIB_RUNLOCK(rh);
-       
        /*
         * Either we hit the root or could not find any match,
         * which basically means: "cannot get there from here".
@@ -748,7 +753,9 @@ ifa_ifwithroute(int flags, const struct sockaddr *dst,
        if (ifa == NULL)
                ifa = ifa_ifwithnet(gateway, 0, fibnum);
        if (ifa == NULL) {
-               struct rtentry *rt = rtalloc1_fib(gateway, 0, 0, fibnum);
+               struct rtentry *rt;
+
+               rt = rtalloc1_fib(gateway, 0, flags, fibnum);
                if (rt == NULL)
                        return (NULL);
                /*
@@ -1838,8 +1845,13 @@ rtrequest1_fib_change(struct rib_head *rnh, struct rt_
            info->rti_info[RTAX_IFP] != NULL ||
            (info->rti_info[RTAX_IFA] != NULL &&
             !sa_equal(info->rti_info[RTAX_IFA], rt->rt_ifa->ifa_addr))) {
-
+               /*
+                * XXX: Temporarily set RTF_RNH_LOCKED flag in the rti_flags
+                *      to avoid rlock in the ifa_ifwithroute().
+                */
+               info->rti_flags |= RTF_RNH_LOCKED;
                error = rt_getifa_fib(info, fibnum);
+               info->rti_flags &= ~RTF_RNH_LOCKED;
                if (info->rti_ifa != NULL)
                        free_ifa = 1;
 

Modified: head/sys/net/route.h
==============================================================================
--- head/sys/net/route.h        Tue Jun 13 10:38:28 2017        (r319894)
+++ head/sys/net/route.h        Tue Jun 13 10:52:31 2017        (r319895)
@@ -189,7 +189,7 @@ struct rtentry {
                                        /* 0x8000000 and up unassigned */
 #define        RTF_STICKY       0x10000000     /* always route dst->src */
 
-#define        RTF_RNH_LOCKED   0x40000000     /* unused */
+#define        RTF_RNH_LOCKED   0x40000000     /* radix node head is locked */
 
 #define        RTF_GWFLAG_COMPAT 0x80000000    /* a compatibility bit for 
interacting
                                           with existing routing apps */
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to