From nobody@FreeBSD.org  Mon May  7 14:34:09 2007
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52])
	by hub.freebsd.org (Postfix) with ESMTP id 2945316A400
	for <freebsd-gnats-submit@FreeBSD.org>; Mon,  7 May 2007 14:34:09 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [69.147.83.33])
	by mx1.freebsd.org (Postfix) with ESMTP id 1C3B313C44B
	for <freebsd-gnats-submit@FreeBSD.org>; Mon,  7 May 2007 14:34:09 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.13.1/8.13.1) with ESMTP id l47EY8UX018293
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 7 May 2007 14:34:08 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.13.1/8.13.1/Submit) id l47ET6gY003252;
	Mon, 7 May 2007 14:29:06 GMT
	(envelope-from nobody)
Message-Id: <200705071429.l47ET6gY003252@www.freebsd.org>
Date: Mon, 7 May 2007 14:29:06 GMT
From: Mehul<mehuljv@yahoo.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: Problem in "rt_check" routine.
X-Send-Pr-Version: www-3.0

>Number:         112490
>Category:       kern
>Synopsis:       [route] [patch] Problem in "rt_check" routine.
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    jhb
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon May 07 14:40:04 GMT 2007
>Closed-Date:    Tue Oct 30 18:08:28 UTC 2007
>Last-Modified:  Tue Oct 30 18:08:28 UTC 2007
>Originator:     Mehul
>Release:        6.2
>Organization:
>Environment:
>Description:
Current implementation of rt_check() routine defined in route.c is
not completely  MPSAFE. I found an issue when i started routing with
"directisr" enabled. For the first rcvd packet this function initializes
rt_gateway of the passed rt_entry. This is done by calling "rtalloc1"
routine. But "rt_check" function doesnt hold any lock while calling this
function. So incase if we have multiple instances of "ip_input - netisr"
running than more than one thread can call this routine which may lead
to some corruption, in my case it leads to a dead lock. Problem doesn't
happen if first a single route packet sent and than heavy traffic. But
if initially itself i send heavy traffic than this happens immediately.
I have fixed this and it works well after it. Patch is attached here
with. This is just a workaround for this issue. Probably we need to
define few macros in route.h for the hardcoded values in the patch.


>How-To-Repeat:

>Fix:
1260a1261
> try_again:
1280a1282,1289
>
>               if(rt0->rt_flags & 0x80000000U){
>                       /*This rt is under process...*/
>                       RT_UNLOCK(rt);
>                       RT_UNLOCK(rt0);
>                       goto try_again;
>               }
>
1281a1291
>                       rt0->rt_flags |= 0x80000000U;
1288a1299
>                       rt0->rt_flags &= (~0x80000000U);

>Release-Note:
>Audit-Trail:

From: John Baldwin <jhb@freebsd.org>
To: bug-followup@freebsd.org, mehuljv@yahoo.com
Cc:  
Subject: Re: kern/112490: [route] [patch] Problem in "rt_check" routine.
Date: Wed, 10 Oct 2007 15:55:01 -0400

 Can you generate a diff with context (such as diff -u)?
 
 -- 
 John Baldwin

From: "Craig Rodrigues" <rodrigc@crodrigues.org>
To: bug-followup@freebsd.org
Cc: mehuljv@yahoo.com, jhb@FreeBSD.org
Subject: Re: kern/112490: [route] [patch] Problem in "rt_check" routine.
Date: Thu, 11 Oct 2007 13:23:34 -0400

 --vkogqOf2sHV7VnPd
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 Hi,
 
 Here is a variation of the patch posted in PR 112490.
 Ivan Voras has tried testing with this, but it didn't solve
 the problem mentioned in PR 112490.
 
 -- 
 Craig Rodrigues
 rodrigc@crodrigues.org
 
 --vkogqOf2sHV7VnPd
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: attachment; filename="a.txt"
 
 Index: route.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/net/route.c,v
 retrieving revision 1.120
 diff -u -r1.120 route.c
 --- route.c	11 Jun 2007 12:19:34 -0000	1.120
 +++ route.c	11 Oct 2007 17:21:15 -0000
 @@ -1281,6 +1281,7 @@
  	int error;
  
  	KASSERT(*lrt0 != NULL, ("rt_check"));
 +try_again:
  	rt = rt0 = *lrt0;
  
  	/* NB: the locking here is tortuous... */
 @@ -1297,11 +1298,19 @@
  	}
  	/* XXX BSD/OS checks dst->sa_family != AF_NS */
  	if (rt->rt_flags & RTF_GATEWAY) {
 -		if (rt->rt_gwroute == NULL)
 +		struct rtentry *temp_rt_gwroute = rt->rt_gwroute;
 +		if (temp_rt_gwroute == NULL)
  			goto lookup;
  		rt = rt->rt_gwroute;
  		RT_LOCK(rt);		/* NB: gwroute */
 +		if(rt0->rt_flags & 0x80000000U){
 +			/*This rt is under process...*/
 +			RT_UNLOCK(rt);
 +			RT_UNLOCK(rt0);
 +			goto try_again;
 +		}
  		if ((rt->rt_flags & RTF_UP) == 0) {
 +			rt0->rt_flags |= 0x80000000U;
  			RTFREE_LOCKED(rt);	/* unlock gwroute */
  			rt = rt0;
  		lookup:
 @@ -1315,6 +1324,7 @@
  			}
  			RT_LOCK(rt0);
  			rt0->rt_gwroute = rt;
 +			rt0->rt_flags &= (~0x80000000U);
  			if (rt == NULL) {
  				RT_UNLOCK(rt0);
  				return (EHOSTUNREACH);
 
 --vkogqOf2sHV7VnPd--

From: John Baldwin <jhb@freebsd.org>
To: mehul vora <mehuljv@yahoo.com>
Cc: bug-followup@freebsd.org
Subject: Re: kern/112490: [route] [patch] Problem in "rt_check" routine.
Date: Thu, 11 Oct 2007 14:37:41 -0400

 On Thursday 11 October 2007 02:24:38 pm mehul vora wrote:
 > will send the patch soon.
 
 FYI, I came up with another patch that may address the issue and is similar to 
 what rt_setgate() does:
 
 Index: route.c
 ===================================================================
 RCS file: /usr/cvs/src/sys/net/route.c,v
 retrieving revision 1.120
 diff -u -r1.120 route.c
 --- route.c	11 Jun 2007 12:19:34 -0000	1.120
 +++ route.c	10 Oct 2007 20:12:54 -0000
 @@ -1314,6 +1314,8 @@
  				return (ENETUNREACH);
  			}
  			RT_LOCK(rt0);
 +			if (rt0->rt_gwroute != NULL)
 +				RTFREE(rt0->rt_gwroute);
  			rt0->rt_gwroute = rt;
  			if (rt == NULL) {
  				RT_UNLOCK(rt0);
 
 
 -- 
 John Baldwin

From: Mehul <mehuljv@gmail.com>
To: bug-followup@FreeBSD.org, mehuljv@yahoo.com
Cc:  
Subject: Re: kern/112490: [route] [patch] Problem in "rt_check" routine.
Date: Mon, 15 Oct 2007 12:58:23 +0530

 ------=_Part_27617_11252248.1192433303334
 Content-Type: multipart/alternative; 
 	boundary="----=_Part_27618_15207532.1192433303335"
 
 ------=_Part_27618_15207532.1192433303335
 Content-Type: text/plain; charset=ISO-8859-1
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline
 
 here is the patch taken with "-u" option.
 
 Mehul.
 
 ------=_Part_27618_15207532.1192433303335
 Content-Type: text/html; charset=ISO-8859-1
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline
 
 here is the patch taken with &quot;-u&quot; option.<br><br>Mehul.<br>
 
 ------=_Part_27618_15207532.1192433303335--
 
 ------=_Part_27617_11252248.1192433303334
 Content-Type: text/plain; name="route_patch"
 Content-Transfer-Encoding: base64
 Content-Disposition: attachment; filename="route_patch"
 X-Attachment-Id: f_f7soadok
 
 LS0tIHJvdXRlX29sZC5jCTIwMDYtMDktMTUgMTM6MTk6NDcuMDAwMDAwMDAwICswNTMwCisrKyBy
 b3V0ZS5jCTIwMDctMDUtMDkgMTY6NTY6MjQuMDAwMDAwMDAwICswNTMwCkBAIC0xMjU4LDYgKzEy
 NTgsNyBAQAogCWludCBlcnJvcjsKIAogCUtBU1NFUlQoKmxydDAgIT0gTlVMTCwgKCJydF9jaGVj
 ayIpKTsKK3RyeV9hZ2FpbjoKIAlydCA9IHJ0MCA9ICpscnQwOwogCiAJLyogTkI6IHRoZSBsb2Nr
 aW5nIGhlcmUgaXMgdG9ydHVvdXMuLi4gKi8KQEAgLTEyNzgsNyArMTI3OSwxNiBAQAogCQkJZ290
 byBsb29rdXA7CiAJCXJ0ID0gcnQtPnJ0X2d3cm91dGU7CiAJCVJUX0xPQ0socnQpOwkJLyogTkI6
 IGd3cm91dGUgKi8KKworCQlpZihydDAtPnJ0X2ZsYWdzICYgMHg4MDAwMDAwMFUpeworCQkJLypU
 aGlzIHJ0IGlzIHVuZGVyIHByb2Nlc3MuLi4qLworCQkJUlRfVU5MT0NLKHJ0KTsKKwkJCVJUX1VO
 TE9DSyhydDApOworCQkJZ290byB0cnlfYWdhaW47CisJCX0KKwogCQlpZiAoKHJ0LT5ydF9mbGFn
 cyAmIFJURl9VUCkgPT0gMCkgeworCQkJcnQwLT5ydF9mbGFncyB8PSAweDgwMDAwMDAwVTsKIAkJ
 CXJ0ZnJlZShydCk7CS8qIHVubG9jayBnd3JvdXRlICovCiAJCQlydCA9IHJ0MDsKIAkJbG9va3Vw
 OgpAQCAtMTI4Niw2ICsxMjk2LDcgQEAKIAkJCXJ0ID0gcnRhbGxvYzEocnQtPnJ0X2dhdGV3YXks
 IDEsIDBVTCk7CiAJCQlSVF9MT0NLKHJ0MCk7CiAJCQlydDAtPnJ0X2d3cm91dGUgPSBydDsKKwkJ
 CXJ0MC0+cnRfZmxhZ3MgJj0gKH4weDgwMDAwMDAwVSk7CiAJCQlpZiAocnQgPT0gTlVMTCkgewog
 CQkJCVJUX1VOTE9DSyhydDApOwogCQkJCXNlbmRlcnIoRUhPU1RVTlJFQUNIKTsK
 ------=_Part_27617_11252248.1192433303334--

From: John Baldwin <john@baldwin.cx>
To: bug-followup@freebsd.org, mehuljv@yahoo.com
Cc:  
Subject: Re: kern/112490: [route] [patch] Problem in "rt_check" routine.
Date: Mon, 15 Oct 2007 16:20:09 -0400

 ru@ pointed out a problem in my earlier patch that could result in some double 
 frees.  Here is an update:
 
 Index: route.c
 ===================================================================
 RCS file: /usr/cvs/src/sys/net/route.c,v
 retrieving revision 1.120
 diff -u -r1.120 route.c
 --- route.c	11 Jun 2007 12:19:34 -0000	1.120
 +++ route.c	15 Oct 2007 19:50:53 -0000
 @@ -1304,6 +1304,7 @@
  		if ((rt->rt_flags & RTF_UP) == 0) {
  			RTFREE_LOCKED(rt);	/* unlock gwroute */
  			rt = rt0;
 +			rt->rt_gwroute = NULL;
  		lookup:
  			RT_UNLOCK(rt0);
  			rt = rtalloc1(rt->rt_gateway, 1, 0UL);
 @@ -1314,6 +1315,8 @@
  				return (ENETUNREACH);
  			}
  			RT_LOCK(rt0);
 +			if (rt0->rt_gwroute != NULL)
 +				RTFREE(rt0->rt_gwroute);
  			rt0->rt_gwroute = rt;
  			if (rt == NULL) {
  				RT_UNLOCK(rt0);
 
 -- 
 John Baldwin
State-Changed-From-To: open->patched 
State-Changed-By: jhb 
State-Changed-When: Mon Oct 22 19:01:38 UTC 2007 
State-Changed-Why:  
Fix committed to HEAD, will be MFC'd to 7.x and 6.x in a week or so. 


Responsible-Changed-From-To: freebsd-bugs->jhb 
Responsible-Changed-By: jhb 
Responsible-Changed-When: Mon Oct 22 19:01:38 UTC 2007 
Responsible-Changed-Why:  
Fix committed to HEAD, will be MFC'd to 7.x and 6.x in a week or so. 

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

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/112490: commit references a PR
Date: Mon, 22 Oct 2007 22:55:55 +0000 (UTC)

 jhb         2007-10-22 19:01:26 UTC
 
   FreeBSD src repository
 
   Modified files:
     sys/net              route.c 
     sys/netinet6         nd6.c 
   Log:
   Close a race when trying to lookup a gateway route in rt_check().
   Specifically, if two threads were doing concurrent lookups and the existing
   gateway was marked down, the the first thread would drop a reference on the
   gateway route and then unlock the "root" route while it tried to allocate
   a new route.  The second thread could then also drop a reference on the
   same gateway route resulting in a reference underflow.  Fix this by
   clearing the gateway route pointer after dropping the reference count but
   before dropping the lock.  Secondly, in this same case, the second thread
   would overwrite the gateway route pointer w/o free'ing a reference to the
   route installed by the first thread.  In practice this would probably just
   fix a lost reference that would result in a route never being freed.
   
   This fixes panics observed in rt_check() and rtexpunge().
   
   MFC after:      1 week
   PR:             kern/112490
   Insight from:   mehuljv at yahoo.com
   Reviewed by:    ru (found the "not-setting it to NULL" part)
   Tested by:      several
   
   Revision  Changes    Path
   1.121     +3 -1      src/sys/net/route.c
   1.84      +3 -1      src/sys/netinet6/nd6.c
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: jhb 
State-Changed-When: Tue Oct 30 18:08:03 UTC 2007 
State-Changed-Why:  
Fix committed to RELENG_[67] and will be in 6.3 and 7.0. 

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