Skip to content

Commit

Permalink
Fix a deadlock with route change when the gateway address is non-local.
Browse files Browse the repository at this point in the history
Ticket #6850
FreeBSD PR: 215122
  • Loading branch information
loos-br committed Dec 8, 2016
1 parent 4fb7ae5 commit 4627301
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 12 deletions.
2 changes: 1 addition & 1 deletion sys/net/radix_mpath.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ rtalloc_mpath_fib(struct route *ro, uint32_t hash, u_int fibnum)
if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)
&& RT_LINK_IS_UP(ro->ro_rt->rt_ifp))
return;
ro->ro_rt = rtalloc1_fib(&ro->ro_dst, 1, 0, fibnum);
ro->ro_rt = rtalloc1_fib(&ro->ro_dst, 1, 0, fibnum, 0);

/* if the route does not exist or it is not multipath, don't care */
if (ro->ro_rt == NULL)
Expand Down
22 changes: 13 additions & 9 deletions sys/net/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ rtalloc_ign_fib(struct route *ro, u_long ignore, u_int fibnum)
RTFREE(rt);
ro->ro_rt = NULL;
}
ro->ro_rt = rtalloc1_fib(&ro->ro_dst, 1, ignore, fibnum);
ro->ro_rt = rtalloc1_fib(&ro->ro_dst, 1, ignore, fibnum, 0);
if (ro->ro_rt)
RT_UNLOCK(ro->ro_rt);
}
Expand All @@ -432,12 +432,12 @@ struct rtentry *
rtalloc1(struct sockaddr *dst, int report, u_long ignflags)
{

return (rtalloc1_fib(dst, report, ignflags, RT_DEFAULT_FIB));
return (rtalloc1_fib(dst, report, ignflags, RT_DEFAULT_FIB, 0));
}

struct rtentry *
rtalloc1_fib(struct sockaddr *dst, int report, u_long ignflags,
u_int fibnum)
rtalloc1_fib(struct sockaddr *dst, int report, u_long ignflags, u_int fibnum,
u_int flags)
{
struct rib_head *rh;
struct radix_node *rn;
Expand All @@ -454,16 +454,18 @@ 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 ((flags & RTF_RNH_LOCKED) == 0)
RIB_RLOCK(rh);
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 ((flags & RTF_RNH_LOCKED) == 0)
RIB_RUNLOCK(rh);
return (newrt);

} else
} else if ((flags & RTF_RNH_LOCKED) == 0)
RIB_RUNLOCK(rh);

/*
Expand Down Expand Up @@ -600,7 +602,7 @@ rtredirect_fib(struct sockaddr *dst,
error = ENETUNREACH;
goto out;
}
rt = rtalloc1_fib(dst, 0, 0UL, fibnum); /* NB: rt is locked */
rt = rtalloc1_fib(dst, 0, 0UL, fibnum, 0); /* NB: rt is locked */
/*
* If the redirect isn't from our current router for this dst,
* it's either old or wrong. If it redirects us to ourselves,
Expand Down Expand Up @@ -749,7 +751,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, 0, fibnum, RTF_RNH_LOCKED);
if (rt == NULL)
return (NULL);
/*
Expand Down
2 changes: 1 addition & 1 deletion sys/net/route.h
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ int rtinit(struct ifaddr *, int, int);
*/
int rt_getifa_fib(struct rt_addrinfo *, u_int fibnum);
void rtalloc_ign_fib(struct route *ro, u_long ignflags, u_int fibnum);
struct rtentry *rtalloc1_fib(struct sockaddr *, int, u_long, u_int);
struct rtentry *rtalloc1_fib(struct sockaddr *, int, u_long, u_int, u_int);
int rtioctl_fib(u_long, caddr_t, u_int);
void rtredirect_fib(struct sockaddr *, struct sockaddr *,
struct sockaddr *, int, struct sockaddr *, u_int);
Expand Down
2 changes: 1 addition & 1 deletion sys/netinet6/in6_rmx.c
Original file line number Diff line number Diff line change
Expand Up @@ -280,5 +280,5 @@ struct rtentry *
in6_rtalloc1(struct sockaddr *dst, int report, u_long ignflags, u_int fibnum)
{

return (rtalloc1_fib(dst, report, ignflags, fibnum));
return (rtalloc1_fib(dst, report, ignflags, fibnum, 0));
}

0 comments on commit 4627301

Please sign in to comment.