diff options
author | Can Erkin Acar <canacar@cvs.openbsd.org> | 2006-11-24 20:57:47 +0000 |
---|---|---|
committer | Can Erkin Acar <canacar@cvs.openbsd.org> | 2006-11-24 20:57:47 +0000 |
commit | 5b423bc8cbec8a172e11bb56d2cc477cd2e853f3 (patch) | |
tree | 5e9474a81bda2627f1626cdf76b296f5e88b21aa | |
parent | c93c037f72b3d139ecafbb6c25719066bd8ea5cd (diff) |
Check the reference count for interface addresses when detaching
an interface. Fixes a double free panic.
ok claudio@, looks fine henning@
-rw-r--r-- | sys/net/if.c | 12 |
1 files changed, 5 insertions, 7 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index 56238f8350e..fe3a6bcc463 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if.c,v 1.151 2006/11/16 13:09:27 henning Exp $ */ +/* $OpenBSD: if.c,v 1.152 2006/11/24 20:57:46 canacar Exp $ */ /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ /* @@ -568,10 +568,8 @@ do { \ /* * Deallocate private resources. - * XXX should consult refcnt and use IFAFREE */ - for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa; - ifa = TAILQ_FIRST(&ifp->if_addrlist)) { + while ((ifa = TAILQ_FIRST(&ifp->if_addrlist)) != NULL) { TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list); #ifdef INET if (ifa->ifa_addr->sa_family == AF_INET) @@ -582,7 +580,7 @@ do { \ if (ifa == ifnet_addrs[ifp->if_index]) continue; - free(ifa, M_IFADDR); + IFAFREE(ifa); } for (ifg = TAILQ_FIRST(&ifp->if_groups); ifg; @@ -591,7 +589,7 @@ do { \ if_free_sadl(ifp); - free(ifnet_addrs[ifp->if_index], M_IFADDR); + IFAFREE(ifnet_addrs[ifp->if_index]); ifnet_addrs[ifp->if_index] = NULL; free(ifp->if_addrhooks, M_TEMP); @@ -1001,9 +999,9 @@ link_rtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info) ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) return; if ((ifa = ifaof_ifpforaddr(dst, ifp)) != NULL) { + ifa->ifa_refcnt++; IFAFREE(rt->rt_ifa); rt->rt_ifa = ifa; - ifa->ifa_refcnt++; if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) ifa->ifa_rtrequest(cmd, rt, info); } |