Date: Mon, 04 Dec 2000 19:31:01 +0000 From: Ian Dowse <iedowse@maths.tcd.ie> To: freebsd-net@freebsd.org Cc: iedowse@maths.tcd.ie Subject: panic in nd6_dad_timer when removing pccard Message-ID: <200012041931.aa09203@salmon.maths.tcd.ie>
next in thread | raw e-mail | index | archive | help
I got a panic today on 4.1-STABLE when removing a pccard shortly after it was inserted. I was running with "options INVARIANTS", which may have helped to trigger the problem. I was able to determine that the panic was caused by an outstanding nd6_dad_timer on a 'struct ifaddr' from a detached interface. The struct ifaddr was still valid, since a reference count system is used; however its ifa_ifp pointed to a memory region that had been freed. I think (though unfortunately I don't have the crash dump any more) that the problem occurred at the lines /* * We have more NS to go. Send NS packet for DAD. */ nd6_dad_ns_output(dp, ifa); dp->dad_timer = timeout((void (*) __P((void *)))nd6_dad_timer, (void *)ifa, nd_ifinfo[ifa->ifa_ifp->if_index].retrans * hz / 1000); since the stale ifa_ifp is dereferenced there. It seems that there is currently no way to determine if a struct ifaddr points to a detached interface - how about a fix such as the one below? It sets all stale ifa_ifp pointers to NULL in if_detach, and checks for this case in nd6_dad_timer. Ian Index: net/if.c =================================================================== RCS file: /home/iedowse/CVS/src/sys/net/if.c,v retrieving revision 1.85.2.3 diff -u -r1.85.2.3 if.c --- net/if.c 2000/08/22 18:06:20 1.85.2.3 +++ net/if.c 2000/12/04 16:23:23 @@ -270,6 +270,7 @@ } #endif /* INET6 */ TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link); + ifa->ifa_ifp = NULL; IFAFREE(ifa); } Index: netinet6/nd6_nbr.c =================================================================== RCS file: /home/iedowse/CVS/src/sys/netinet6/nd6_nbr.c,v retrieving revision 1.4.2.2 diff -u -r1.4.2.2 nd6_nbr.c --- netinet6/nd6_nbr.c 2000/07/15 07:14:36 1.4.2.2 +++ netinet6/nd6_nbr.c 2000/12/04 16:29:18 @@ -1083,6 +1083,14 @@ log(LOG_ERR, "nd6_dad_timer: DAD structure not found\n"); goto done; } + if (ifa->ifa_ifp == NULL) { + /* Interface has gone away */ + TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list); + free(dp, M_IP6NDP); + dp = NULL; + IFAFREE(ifa); + goto done; + } if (ia->ia6_flags & IN6_IFF_DUPLICATED) { log(LOG_ERR, "nd6_dad_timer: called with duplicated address " "%s(%s)\n", To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-net" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi? <200012041931.aa09203>