Skip site navigation (1)Skip section navigation (2)
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>