Subject: Re: kern/21189
To: None <netbsd-bugs@netbsd.org, gnats-admin@netbsd.org,>
From: Matthias Scheler <tron@zhadum.de>
List: netbsd-bugs
Date: 04/02/2005 23:44:50
On Fri, Mar 11, 2005 at 05:57:45PM +0000, tron@netbsd.org wrote:
> Synopsis: ifconfig + stf0 make kernel crash with uvm fault
> 
> State-Changed-From-To: open->analyzed
> State-Changed-By: tron@netbsd.org
> State-Changed-When: Fri, 11 Mar 2005 17:57:44 +0000
> State-Changed-Why:
> I can still reproduce the problem under NetBSD 2.99.16. Examining a crash
> dump I found out that:
> 
> 1.) The kernel crashes because it tries to use a "struct ifnet" which
>     has been free()d before.
> 
> 2.) The bogus "struct ifnet *" pointer comes from the ND prefix list
>     which is walked in nd6_prefix_offlink() in line 1574-1603.

I think I've found the reason for the problem described above:

if_detach() removes all addresses from the interface without releasing
the reference on the "nd_prefix" which has been acquired in in6_control()
while handling an SIOCAIFADDR_IN6 ioctl. When nd6_purge() afterwards calls
prelist_remove() the prefix will not be purged because the reference
count is larger than zero. At some point the kernel will find the prefix
with the stale "struct ifnet *" pointer and panic.

The following change fix the problem for me:

Index: nd6.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/nd6.c,v
retrieving revision 1.91
diff -u -r1.91 nd6.c
--- nd6.c	4 Dec 2004 16:10:25 -0000	1.91
+++ nd6.c	2 Apr 2005 22:37:58 -0000
@@ -636,6 +636,7 @@
 	for (pr = nd_prefix.lh_first; pr; pr = npr) {
 		npr = pr->ndpr_next;
 		if (pr->ndpr_ifp == ifp) {
+			pr->ndpr_refcnt = 0;
 			/*
 			 * Previously, pr->ndpr_addr is removed as well,
 			 * but I strongly believe we don't have to do it.

"nd_prefix" structures are interface specific and should therefore always
be purged when an interface is destroyed. The above change makes sure
that this will always happen.

	Kind regards
 
-- 
Matthias Scheler                                  http://scheler.de/~matthias/