summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorae <ae@FreeBSD.org>2017-06-20 05:57:28 +0000
committerae <ae@FreeBSD.org>2017-06-20 05:57:28 +0000
commit457477d4a00788883d774cda30eda7fa4afa921f (patch)
tree256ce820a420731becb4bd2268199ae1137030c0
parent5069a7986d5c3dc517d4a5b5eaa0c15207bf71c7 (diff)
downloadFreeBSD-src-457477d4a00788883d774cda30eda7fa4afa921f.zip
FreeBSD-src-457477d4a00788883d774cda30eda7fa4afa921f.tar.gz
MFC r319895:
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 Sponsored by: Yandex LLC Approved by: re (delphij)
-rw-r--r--sys/net/route.c24
-rw-r--r--sys/net/route.h2
2 files changed, 19 insertions, 7 deletions
diff --git a/sys/net/route.c b/sys/net/route.c
index 5c6d526..3652eb4 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -454,18 +454,23 @@ rtalloc1_fib(struct sockaddr *dst, int report, u_long ignflags,
/*
* 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, struct sockaddr *gateway,
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_addrinfo *info,
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;
diff --git a/sys/net/route.h b/sys/net/route.h
index b6aa36d..d76ed70 100644
--- a/sys/net/route.h
+++ b/sys/net/route.h
@@ -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 */
OpenPOWER on IntegriCloud