diff options
author | delphij <delphij@FreeBSD.org> | 2010-09-27 19:26:56 +0000 |
---|---|---|
committer | delphij <delphij@FreeBSD.org> | 2010-09-27 19:26:56 +0000 |
commit | f0a3248def60f8c0835ab4354386d7ce007771bc (patch) | |
tree | ad4db2ca515fc0cc41a568c55ee278cd8c7587ce /sys/netinet6 | |
parent | 3d9c031cfc23f4e72fda525c5941b62635e7abde (diff) | |
download | FreeBSD-src-f0a3248def60f8c0835ab4354386d7ce007771bc.zip FreeBSD-src-f0a3248def60f8c0835ab4354386d7ce007771bc.tar.gz |
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
Diffstat (limited to 'sys/netinet6')
-rw-r--r-- | sys/netinet6/in6_rmx.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/sys/netinet6/in6_rmx.c b/sys/netinet6/in6_rmx.c index 8927a17..2a13646 100644 --- a/sys/netinet6/in6_rmx.c +++ b/sys/netinet6/in6_rmx.c @@ -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; } |