From nobody@FreeBSD.org  Sat Dec 20 20:51:38 2008
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id D085F1065674
	for <freebsd-gnats-submit@FreeBSD.org>; Sat, 20 Dec 2008 20:51:38 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id BE1508FC22
	for <freebsd-gnats-submit@FreeBSD.org>; Sat, 20 Dec 2008 20:51:38 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id mBKKpb0P036739
	for <freebsd-gnats-submit@FreeBSD.org>; Sat, 20 Dec 2008 20:51:37 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id mBKKpbhN036738;
	Sat, 20 Dec 2008 20:51:37 GMT
	(envelope-from nobody)
Message-Id: <200812202051.mBKKpbhN036738@www.freebsd.org>
Date: Sat, 20 Dec 2008 20:51:37 GMT
From: Dheeraj Reddy <dheeraj@ece.gatech.edu>
To: freebsd-gnats-submit@FreeBSD.org
Subject: Locking related leaks in the kernel (routing handling)
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         129793
>Category:       kern
>Synopsis:       [ip6] [patch] Locking related leaks in the kernel (routing handling)
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    bz
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Dec 20 21:00:02 UTC 2008
>Closed-Date:    Tue Aug 25 19:15:12 UTC 2009
>Last-Modified:  Tue Aug 25 19:15:12 UTC 2009
>Originator:     Dheeraj Reddy
>Release:        FreeBSD-current
>Organization:
Intel
>Environment:
/var/log % uname -a
FreeBSD vagisha.sudheeraj.net 8.0-CURRENT FreeBSD 8.0-CURRENT #1 r186333M: Sat Dec 20 12:22:11 PST 2008     dheeraj@vagisha.sudheeraj.net:/usr/src/sys/i386/compile/VAGISHA-CURRENT  i386


>Description:
I have a gif tunnel setup to hurricane electric.
When I have ipv6 traffic, I get the following kernel messages

Dec 20 00:15:42 vagisha kernel: rtfree: 0xc22e0958 has 1 refs
Dec 20 00:16:18 vagisha kernel: rtfree: 0xc22e0958 has 1 refs
Dec 20 01:03:14 vagisha kernel: rtfree: 0xc22e0958 has 1 refs
Dec 20 01:04:27 vagisha kernel: rtfree: 0xc22e0958 has 1 refs
Dec 20 03:01:01 vagisha kernel: rtfree: 0xc22e0958 has 1 refs
Dec 20 08:34:35 vagisha kernel: rtfree: 0xc22e0958 has 1 refs

netstat -rAn shows that 0xC22e0958 is he default route for ipv6 traffic via gif0 
c22e0958 fe80::%gif0/64                    link#6                        U        gif0          mask (255) ffff ffff ffff ffff ffff ffff ffff



>How-To-Repeat:
Setup a gif tunnel to a tunnelbroker and just send some icmp traffic over the ipv6 network.


>Fix:
Patch attached.
rtalloc1 returns a locked route entry.. so we should use RTFREE_LOCKED instead of rtfree.

Patch attached with submission follows:

Index: netinet6/in6_ifattach.c
===================================================================
--- netinet6/in6_ifattach.c	(revision 186333)
+++ netinet6/in6_ifattach.c	(working copy)
@@ -778,7 +778,7 @@
 		if ((ia->ia_flags & IFA_ROUTE) &&
 		    (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0, 0UL))) {
 			rtflags = rt->rt_flags;
-			rtfree(rt);
+			RTFREE_LOCKED(rt);
 			rtrequest(RTM_DELETE, (struct sockaddr *)&ia->ia_addr,
 			    (struct sockaddr *)&ia->ia_addr,
 			    (struct sockaddr *)&ia->ia_prefixmask,
Index: netinet6/nd6_nbr.c
===================================================================
--- netinet6/nd6_nbr.c	(revision 186333)
+++ netinet6/nd6_nbr.c	(working copy)
@@ -259,7 +259,7 @@
 		need_proxy = (rt && (rt->rt_flags & RTF_ANNOUNCE) != 0 &&
 		    rt->rt_gateway->sa_family == AF_LINK);
 		if (rt)
-			rtfree(rt);
+			RTFREE_LOCKED(rt);
 		if (need_proxy) {
 			/*
 			 * proxy NDP for single entry
Index: netinet6/in6.c
===================================================================
--- netinet6/in6.c	(revision 186333)
+++ netinet6/in6.c	(working copy)
@@ -2141,16 +2141,16 @@
 		ifa = ifaof_ifpforaddr(__DECONST(struct sockaddr *, l3addr), ifp);
 		if (ifa != NULL) {
 			if (rt != NULL)
-				rtfree(rt);
+				RTFREE_LOCKED(rt);
 			return 0;
 		}
 		log(LOG_INFO, "IPv6 address: \"%s\" is not on the network\n",
 		    ip6_sprintf(ip6buf, &((const struct sockaddr_in6 *)l3addr)->sin6_addr));
 		if (rt != NULL)
-			rtfree(rt);
+			RTFREE_LOCKED(rt);
 		return EINVAL;
 	}
-	rtfree(rt);
+	RTFREE_LOCKED(rt);
 	return 0;
 }
 
Index: netinet6/in6_gif.c
===================================================================
--- netinet6/in6_gif.c	(revision 186333)
+++ netinet6/in6_gif.c	(working copy)
@@ -375,10 +375,10 @@
 			    ip6_sprintf(ip6buf, &sin6.sin6_addr));
 #endif
 			if (rt)
-				rtfree(rt);
+				RTFREE_LOCKED(rt);
 			return 0;
 		}
-		rtfree(rt);
+		RTFREE_LOCKED(rt);
 	}
 
 	return 128 * 2;


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-net 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Mon Dec 22 05:24:08 UTC 2008 
Responsible-Changed-Why:  
Over to maintainer(s). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=129793 
State-Changed-From-To: open->analyzed 
State-Changed-By: bz 
State-Changed-When: Fri Jan 30 23:13:14 UTC 2009 
State-Changed-Why:  
Found more new code with the same problems. 
I have to ponder a bit more on the in6_ifattach.c one 
before going to commit things. 


Responsible-Changed-From-To: freebsd-net->bz 
Responsible-Changed-By: bz 
Responsible-Changed-When: Fri Jan 30 23:13:14 UTC 2009 
Responsible-Changed-Why:  
I had a look, so handle this one. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=129793 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/129793: commit references a PR
Date: Sat, 31 Jan 2009 10:48:13 +0000 (UTC)

 Author: bz
 Date: Sat Jan 31 10:48:02 2009
 New Revision: 187946
 URL: http://svn.freebsd.org/changeset/base/187946
 
 Log:
   Like with r185713 make sure to not leak a lock as rtalloc1(9) returns
   a locked route. Thus we have to use RTFREE_LOCKED(9) to get it unlocked
   and rtfree(9)d rather than just rtfree(9)d.
   
   Since the PR was filed, new places with the same problem were added
   with new code.  Also check that the rt is valid before freeing it
   either way there.
   
   PR:		kern/129793
   Submitted by:	Dheeraj Reddy <dheeraj@ece.gatech.edu>
   MFC after:	2 weeks
   Committed from:	Bugathon #6
 
 Modified:
   head/sys/net/if_llatbl.c
   head/sys/netinet6/in6.c
   head/sys/netinet6/in6_gif.c
   head/sys/netinet6/in6_ifattach.c
   head/sys/netinet6/nd6_nbr.c
 
 Modified: head/sys/net/if_llatbl.c
 ==============================================================================
 --- head/sys/net/if_llatbl.c	Sat Jan 31 10:04:36 2009	(r187945)
 +++ head/sys/net/if_llatbl.c	Sat Jan 31 10:48:02 2009	(r187946)
 @@ -219,10 +219,11 @@ lla_rt_output(struct rt_msghdr *rtm, str
  					log(LOG_INFO, "%s: RTM_ADD publish "
  					    "(proxy only) is invalid\n",
  					    __func__);
 -					RTFREE(rt);
 +					if (rt)
 +						RTFREE_LOCKED(rt);
  					return EINVAL;
  				}
 -				RTFREE(rt);
 +				RTFREE_LOCKED(rt);
  
  				flags |= LLE_PROXY;
  			}
 
 Modified: head/sys/netinet6/in6.c
 ==============================================================================
 --- head/sys/netinet6/in6.c	Sat Jan 31 10:04:36 2009	(r187945)
 +++ head/sys/netinet6/in6.c	Sat Jan 31 10:48:02 2009	(r187946)
 @@ -2122,16 +2122,16 @@ in6_lltable_rtcheck(struct ifnet *ifp, c
  		ifa = ifaof_ifpforaddr(__DECONST(struct sockaddr *, l3addr), ifp);
  		if (ifa != NULL) {
  			if (rt != NULL)
 -				rtfree(rt);
 +				RTFREE_LOCKED(rt);
  			return 0;
  		}
  		log(LOG_INFO, "IPv6 address: \"%s\" is not on the network\n",
  		    ip6_sprintf(ip6buf, &((const struct sockaddr_in6 *)l3addr)->sin6_addr));
  		if (rt != NULL)
 -			rtfree(rt);
 +			RTFREE_LOCKED(rt);
  		return EINVAL;
  	}
 -	rtfree(rt);
 +	RTFREE_LOCKED(rt);
  	return 0;
  }
  
 
 Modified: head/sys/netinet6/in6_gif.c
 ==============================================================================
 --- head/sys/netinet6/in6_gif.c	Sat Jan 31 10:04:36 2009	(r187945)
 +++ head/sys/netinet6/in6_gif.c	Sat Jan 31 10:48:02 2009	(r187946)
 @@ -378,10 +378,10 @@ gif_validate6(const struct ip6_hdr *ip6,
  			    ip6_sprintf(ip6buf, &sin6.sin6_addr));
  #endif
  			if (rt)
 -				rtfree(rt);
 +				RTFREE_LOCKED(rt);
  			return 0;
  		}
 -		rtfree(rt);
 +		RTFREE_LOCKED(rt);
  	}
  
  	return 128 * 2;
 
 Modified: head/sys/netinet6/in6_ifattach.c
 ==============================================================================
 --- head/sys/netinet6/in6_ifattach.c	Sat Jan 31 10:04:36 2009	(r187945)
 +++ head/sys/netinet6/in6_ifattach.c	Sat Jan 31 10:48:02 2009	(r187946)
 @@ -778,7 +778,7 @@ in6_ifdetach(struct ifnet *ifp)
  		if ((ia->ia_flags & IFA_ROUTE) &&
  		    (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0, 0UL))) {
  			rtflags = rt->rt_flags;
 -			rtfree(rt);
 +			RTFREE_LOCKED(rt);
  			rtrequest(RTM_DELETE, (struct sockaddr *)&ia->ia_addr,
  			    (struct sockaddr *)&ia->ia_addr,
  			    (struct sockaddr *)&ia->ia_prefixmask,
 
 Modified: head/sys/netinet6/nd6_nbr.c
 ==============================================================================
 --- head/sys/netinet6/nd6_nbr.c	Sat Jan 31 10:04:36 2009	(r187945)
 +++ head/sys/netinet6/nd6_nbr.c	Sat Jan 31 10:48:02 2009	(r187946)
 @@ -259,7 +259,7 @@ nd6_ns_input(struct mbuf *m, int off, in
  		need_proxy = (rt && (rt->rt_flags & RTF_ANNOUNCE) != 0 &&
  		    rt->rt_gateway->sa_family == AF_LINK);
  		if (rt)
 -			rtfree(rt);
 +			RTFREE_LOCKED(rt);
  		if (need_proxy) {
  			/*
  			 * proxy NDP for single entry
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: analyzed->patched 
State-Changed-By: bz 
State-Changed-When: Sat Jan 31 10:55:29 UTC 2009 
State-Changed-Why:  
r187946 comitted to HEAD. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=129793 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/129793: commit references a PR
Date: Tue, 25 Aug 2009 19:04:40 +0000 (UTC)

 Author: bz
 Date: Tue Aug 25 19:04:22 2009
 New Revision: 196549
 URL: http://svn.freebsd.org/changeset/base/196549
 
 Log:
   MFC r187946:
     Like with r185713 make sure to not leak a lock as rtalloc1(9) returns
     a locked route. Thus we have to use RTFREE_LOCKED(9) to get it unlocked
     and rtfree(9)d rather than just rtfree(9)d.
   
     PR:		kern/129793
     Submitted by:	Dheeraj Reddy <dheeraj@ece.gatech.edu>
     Originally committed from:       Bugathon #6
 
 Modified:
   stable/7/sys/   (props changed)
   stable/7/sys/contrib/pf/   (props changed)
   stable/7/sys/netinet6/in6_gif.c
   stable/7/sys/netinet6/in6_ifattach.c
   stable/7/sys/netinet6/nd6_nbr.c
 
 Modified: stable/7/sys/netinet6/in6_gif.c
 ==============================================================================
 --- stable/7/sys/netinet6/in6_gif.c	Tue Aug 25 17:00:24 2009	(r196548)
 +++ stable/7/sys/netinet6/in6_gif.c	Tue Aug 25 19:04:22 2009	(r196549)
 @@ -389,10 +389,10 @@ gif_validate6(const struct ip6_hdr *ip6,
  			    ip6_sprintf(ip6buf, &sin6.sin6_addr));
  #endif
  			if (rt)
 -				rtfree(rt);
 +				RTFREE_LOCKED(rt);
  			return 0;
  		}
 -		rtfree(rt);
 +		RTFREE_LOCKED(rt);
  	}
  
  	return 128 * 2;
 
 Modified: stable/7/sys/netinet6/in6_ifattach.c
 ==============================================================================
 --- stable/7/sys/netinet6/in6_ifattach.c	Tue Aug 25 17:00:24 2009	(r196548)
 +++ stable/7/sys/netinet6/in6_ifattach.c	Tue Aug 25 19:04:22 2009	(r196549)
 @@ -767,7 +767,7 @@ in6_ifdetach(struct ifnet *ifp)
  		if ((ia->ia_flags & IFA_ROUTE) &&
  		    (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0, 0UL))) {
  			rtflags = rt->rt_flags;
 -			rtfree(rt);
 +			RTFREE_LOCKED(rt);
  			rtrequest(RTM_DELETE, (struct sockaddr *)&ia->ia_addr,
  			    (struct sockaddr *)&ia->ia_addr,
  			    (struct sockaddr *)&ia->ia_prefixmask,
 
 Modified: stable/7/sys/netinet6/nd6_nbr.c
 ==============================================================================
 --- stable/7/sys/netinet6/nd6_nbr.c	Tue Aug 25 17:00:24 2009	(r196548)
 +++ stable/7/sys/netinet6/nd6_nbr.c	Tue Aug 25 19:04:22 2009	(r196549)
 @@ -236,7 +236,7 @@ nd6_ns_input(struct mbuf *m, int off, in
  		need_proxy = (rt && (rt->rt_flags & RTF_ANNOUNCE) != 0 &&
  		    rt->rt_gateway->sa_family == AF_LINK);
  		if (rt)
 -			rtfree(rt);
 +			RTFREE_LOCKED(rt);
  		if (need_proxy) {
  			/*
  			 * proxy NDP for single entry
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: bz 
State-Changed-When: Tue Aug 25 19:13:31 UTC 2009 
State-Changed-Why:  
Merged what was needed. Thanks a lot for reporting and the patch! 

http://www.freebsd.org/cgi/query-pr.cgi?pr=129793 
>Unformatted:
