kernel panic
Sepherosa Ziehau
sepherosa at gmail.com
Fri Dec 28 04:45:02 PST 2007
On Sep 17, 2007 10:32 AM, Peter Avalos <pavalos at theshell.com> wrote:
>
> 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?
My question about the panic is:
Have you assigned IP address to the tap(4) device via -I option to vkernel?
The patch looks good to me; it still needs little modification tho.
If you had not assign IP address to tap(4) then I think this patch
probably won't fix your panic.
Best Regards,
sephe
>
> 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);
>
--
Live Free or Die
More information about the Bugs
mailing list