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