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>
