kernel panic

Peter Avalos pavalos at theshell.com
Sun Sep 16 19:37:13 PDT 2007


On Sat, Sep 01, 2007 at 05:54:10PM -0400, Peter Avalos wrote:
> On Wed, Aug 29, 2007 at 09:50:27PM -0700, Matthew Dillon wrote:
> > 
> >     So we need to audit all the code that manipulates the in_ifaddrhead 
> >     list and check for structures that might get freed without being removed
> >     from the list.
> > 
> 
> I'm having no luck.  Got any pointers/ideas?
> 

Looking around FreeBSD source I saw this, and was wondering if it could
help?

http://www.theshell.com/cgi-bin/gitweb.cgi?p=freebsd-src.git;a=commitdiff;h=16f96b132d344c7682df05b3bf74278150a5b3b1

commit 16f96b132d344c7682df05b3bf74278150a5b3b1
Author: peadar <peadar>
Date:   Wed May 25 13:52:03 2005 +0000

    Separate out address-detaching part of if_detach into if_purgeaddrs,
    so if_tap doesn't need to rely on locally-rolled code to do same.
    
    The observable symptom of if_tap's bzero'ing the address details
    was a crash in "ifconfig tap0" after an if_tap device was closed.
    
    Reported By: Matti Saarinen (mjsaarin at cc dot helsinki dot fi)

diff --git a/sys/net/if.c b/sys/net/if.c
index 8aff428..f056329 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)if.c	8.5 (Berkeley) 1/9/95
- * $FreeBSD: src/sys/net/if.c,v 1.227 2005/04/20 09:30:54 glebius Exp $
+ * $FreeBSD: src/sys/net/if.c,v 1.228 2005/05/25 13:52:03 peadar Exp $
  */
 
 #include "opt_compat.h"
@@ -530,13 +530,52 @@ if_attachdomain1(struct ifnet *ifp)
 }
 
 /*
+ * Remove any network addresses from an interface.
+ */
+
+void
+if_purgeaddrs(struct ifnet *ifp)
+{
+	struct ifaddr *ifa, *next;
+
+	TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, next) {
+
+		if (ifa->ifa_addr->sa_family == AF_LINK)
+			continue;
+#ifdef INET
+		/* XXX: Ugly!! ad hoc just for INET */
+		if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET) {
+			struct ifaliasreq ifr;
+
+			bzero(&ifr, sizeof(ifr));
+			ifr.ifra_addr = *ifa->ifa_addr;
+			if (ifa->ifa_dstaddr)
+				ifr.ifra_broadaddr = *ifa->ifa_dstaddr;
+			if (in_control(NULL, SIOCDIFADDR, (caddr_t)&ifr, ifp,
+			    NULL) == 0)
+				continue;
+		}
+#endif /* INET */
+#ifdef INET6
+		if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET6) {
+			in6_purgeaddr(ifa);
+			/* ifp_addrhead is already updated */
+			continue;
+		}
+#endif /* INET6 */
+		TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
+		IFAFREE(ifa);
+	}
+}
+
+/*
  * Detach an interface, removing it from the
  * list of "active" interfaces.
  */
 void
 if_detach(struct ifnet *ifp)
 {
-	struct ifaddr *ifa, *next;
+	struct ifaddr *ifa;
 	struct radix_node_head	*rnh;
 	int s;
 	int i;
@@ -568,35 +607,7 @@ if_detach(struct ifnet *ifp)
 		altq_detach(&ifp->if_snd);
 #endif
 
-	for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa; ifa = next) {
-		next = TAILQ_NEXT(ifa, ifa_link);
-
-		if (ifa->ifa_addr->sa_family == AF_LINK)
-			continue;
-#ifdef INET
-		/* XXX: Ugly!! ad hoc just for INET */
-		if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET) {
-			struct ifaliasreq ifr;
-
-			bzero(&ifr, sizeof(ifr));
-			ifr.ifra_addr = *ifa->ifa_addr;
-			if (ifa->ifa_dstaddr)
-				ifr.ifra_broadaddr = *ifa->ifa_dstaddr;
-			if (in_control(NULL, SIOCDIFADDR, (caddr_t)&ifr, ifp,
-			    NULL) == 0)
-				continue;
-		}
-#endif /* INET */
-#ifdef INET6
-		if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET6) {
-			in6_purgeaddr(ifa);
-			/* ifp_addrhead is already updated */
-			continue;
-		}
-#endif /* INET6 */
-		TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
-		IFAFREE(ifa);
-	}
+	if_purgeaddrs(ifp);
 
 #ifdef INET6
 	/*
diff --git a/sys/net/if_tap.c b/sys/net/if_tap.c
index 232c96d..a807bd5 100644
--- a/sys/net/if_tap.c
+++ b/sys/net/if_tap.c
@@ -31,7 +31,7 @@
  */
 
 /*
- * $FreeBSD: src/sys/net/if_tap.c,v 1.53 2005/05/04 18:55:02 emax Exp $
+ * $FreeBSD: src/sys/net/if_tap.c,v 1.54 2005/05/25 13:52:03 peadar Exp $
  * $Id: if_tap.c,v 0.21 2000/07/23 21:46:02 max Exp $
  */
 
@@ -408,6 +408,7 @@ tapclose(dev, foo, bar, td)
 	int		 bar;
 	struct thread	*td;
 {
+	struct ifaddr *ifa;
 	struct tap_softc	*tp = dev->si_drv1;
 	struct ifnet		*ifp = &tp->tap_if;
 	int			s;
@@ -426,24 +427,10 @@ tapclose(dev, foo, bar, td)
 		s = splimp();
 		if_down(ifp);
 		if (ifp->if_flags & IFF_RUNNING) {
-			/* find internet addresses and delete routes */
-			struct ifaddr	*ifa = NULL;
-
-			/* In desparate need of ifaddr locking. */
 			TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
-				if (ifa->ifa_addr->sa_family == AF_INET) {
-					rtinit(ifa, (int)RTM_DELETE, 0);
-
-					/* remove address from interface */
-					bzero(ifa->ifa_addr,
-						   sizeof(*(ifa->ifa_addr)));
-					bzero(ifa->ifa_dstaddr,
-						   sizeof(*(ifa->ifa_dstaddr)));
-					bzero(ifa->ifa_netmask,
-						   sizeof(*(ifa->ifa_netmask)));
-				}
+				rtinit(ifa, (int)RTM_DELETE, 0);
 			}
-
+			if_purgeaddrs(ifp);
 			ifp->if_flags &= ~IFF_RUNNING;
 		}
 		splx(s);
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index ab8d389..6d9cbed 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  *	From: @(#)if.h	8.1 (Berkeley) 6/10/93
- * $FreeBSD: src/sys/net/if_var.h,v 1.95 2005/04/20 09:30:54 glebius Exp $
+ * $FreeBSD: src/sys/net/if_var.h,v 1.96 2005/05/25 13:52:03 peadar Exp $
  */
 
 #ifndef	_NET_IF_VAR_H_
@@ -629,6 +629,7 @@ int	if_allmulti(struct ifnet *, int);
 void	if_attach(struct ifnet *);
 int	if_delmulti(struct ifnet *, struct sockaddr *);
 void	if_detach(struct ifnet *);
+void	if_purgeaddrs(struct ifnet *);
 void	if_down(struct ifnet *);
 void	if_initname(struct ifnet *, const char *, int);
 void	if_link_state_change(struct ifnet *, int);
Attachment:
pgp00008.pgp
-------------- next part --------------
A non-text attachment was scrubbed...
Name: pgp00008.pgp
Type: application/octet-stream
Size: 189 bytes
Desc: "Description: PGP signature"
URL: <http://lists.dragonflybsd.org/pipermail/bugs/attachments/20070916/5608a1c9/attachment-0022.obj>


More information about the Bugs mailing list