Add a bandaid for a long-standing race condition during route entry
un-expiring. The previous version of code have no locking when testing rt_refcnt. The result of the lack of locking may result in a condition where a routing entry have a reference count but at the same time have RTPRF_OURS bit set and an expiration timer. These would eventually lead to a panic: panic: rtqkill route really not free When the system have ICMP redirects accepted from local gateway in a moderate frequency, for instance. Commit this workaround for now until we have some better solution. PR: kern/149804 Reviewed by: bz Tested by: Zhao Xin, Pete French MFC after: 2 weeks
This commit is contained in:
parent
0d2d8fab68
commit
64e0f48e7c
@ -121,12 +121,13 @@ in_matroute(void *v_arg, struct radix_node_head *head)
|
||||
struct radix_node *rn = rn_match(v_arg, head);
|
||||
struct rtentry *rt = (struct rtentry *)rn;
|
||||
|
||||
/*XXX locking? */
|
||||
if (rt && rt->rt_refcnt == 0) { /* this is first reference */
|
||||
if (rt) {
|
||||
RT_LOCK(rt);
|
||||
if (rt->rt_flags & RTPRF_OURS) {
|
||||
rt->rt_flags &= ~RTPRF_OURS;
|
||||
rt->rt_rmx.rmx_expire = 0;
|
||||
}
|
||||
RT_UNLOCK(rt);
|
||||
}
|
||||
return rn;
|
||||
}
|
||||
|
@ -193,11 +193,13 @@ in6_matroute(void *v_arg, struct radix_node_head *head)
|
||||
struct radix_node *rn = rn_match(v_arg, head);
|
||||
struct rtentry *rt = (struct rtentry *)rn;
|
||||
|
||||
if (rt && rt->rt_refcnt == 0) { /* this is first reference */
|
||||
if (rt) {
|
||||
RT_LOCK(rt);
|
||||
if (rt->rt_flags & RTPRF_OURS) {
|
||||
rt->rt_flags &= ~RTPRF_OURS;
|
||||
rt->rt_rmx.rmx_expire = 0;
|
||||
}
|
||||
RT_UNLOCK(rt);
|
||||
}
|
||||
return rn;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user