From iedowse@maths.tcd.ie  Fri Mar 24 10:06:20 2000
Return-Path: <iedowse@maths.tcd.ie>
Received: from salmon.maths.tcd.ie (salmon.maths.tcd.ie [134.226.81.11])
	by hub.freebsd.org (Postfix) with SMTP id CD70537B885
	for <freebsd-gnats-submit@freebsd.org>; Fri, 24 Mar 2000 10:06:10 -0800 (PST)
	(envelope-from iedowse@maths.tcd.ie)
Received: from walton.maths.tcd.ie by salmon.maths.tcd.ie with SMTP
          id <aa96710@salmon>; 24 Mar 2000 18:06:08 +0000 (GMT)
Message-Id: <200003241806.aa98076@walton.maths.tcd.ie>
Date: Fri, 24 Mar 2000 18:06:08 +0000 (GMT)
From: iedowse@maths.tcd.ie
Sender: iedowse@maths.tcd.ie
Reply-To: iedowse@maths.tcd.ie
To: FreeBSD-gnats-submit@freebsd.org
Subject: NETATALK code can corrupt mbuf free lists
X-Send-Pr-Version: 3.2

>Number:         17583
>Category:       kern
>Synopsis:       NETATALK code can corrupt mbuf free lists
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    iedowse
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Mar 24 10:10:01 PST 2000
>Closed-Date:    Sat Jun 23 13:43:21 PDT 2001
>Last-Modified:  Sat Jun 23 13:56:14 PDT 2001
>Originator:     Ian Dowse
>Release:        FreeBSD 3.4-STABLE i386
>Organization:
		School of Mathematics
		Trinity College, Dublin
>Environment:

	FreeBSD -current, but problem exists in 4.0-STABLE and 3.x

>Description:

	In certain circumstances, the NETATALK code can cause an mbuf
	chain to be freed multiple times.

	The code uses a 'struct aarptab' to store information about
	appletalk addresses, which includes an mbuf pointer 'aap_hold'.
	In most places, the code is careful about ensuring that mbuf
	chains referenced by this mechanism are freed only once, but
	there is a subtle problem in at_aarpinput(). The code fragment
	looks something like:

 	if (aat->aat_hold != NULL) {
	    (*ac->ac_if.if_output)(&ac->ac_if, aat->aat_hold, ...);
 	    aat->aat_hold = NULL;
 	}

	The problem here is that when if_output() is called,
	aat->aat_hold contains a non-NULL pointer. If the interface
	if_output routine calls aarpresolve(), then aarpresolve()
	may free aat->aat_hold. This can result in aat_hold being
	m_freem'd twice, since if_output will also free it.

	The simple solution is to ensure that aat_hold is NULLed out
	before calling the if_output routine. The patch below does
	this by copying the mbuf pointer into a local variable
	so that aat->aat_hold can be NULL when if_output is called.

>How-To-Repeat:

	Connecting a FreeBSD router to a busy network seemed to
	trigger this problem every few hours, but it should be easy
	to construct a sequence of packet arrivals which cause it
	directly.

>Fix:


--- aarp.c.orig	Fri Mar 24 16:26:08 2000
+++ aarp.c	Fri Mar 24 17:48:12 2000
@@ -393,12 +393,20 @@
 		sizeof( ea->aarp_sha ));
 	aat->aat_flags |= ATF_COM;
 	if ( aat->aat_hold ) {
+	    struct mbuf *mhold;
+
+	    /*
+	     * We must NULL out the aat->aat_hold pointer, since otherwise
+	     * if_output may call aarpresolve() which could m_freem() it.
+	     */
+	    mhold = aat->aat_hold;
+	    aat->aat_hold = NULL;
+
 	    sat.sat_len = sizeof(struct sockaddr_at);
 	    sat.sat_family = AF_APPLETALK;
 	    sat.sat_addr = spa;
-	    (*ac->ac_if.if_output)( &ac->ac_if, aat->aat_hold,
+	    (*ac->ac_if.if_output)( &ac->ac_if, mhold,
 		    (struct sockaddr *)&sat, NULL); /* XXX */
-	    aat->aat_hold = 0;
 	}
     }
 

>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->julian 
Responsible-Changed-By: sheldonh 
Responsible-Changed-When: Wed Mar 29 02:08:04 PST 2000 
Responsible-Changed-Why:  
Julian, could you check this one out?  Ian submits quality PR's. :-) 
Responsible-Changed-From-To: julian->	 iedowse 
Responsible-Changed-By: bmilekic 
Responsible-Changed-When: Mon Jun 4 14:49:16 PDT 2001 
Responsible-Changed-Why:  
Ian Dowse is now a committer. Ian, I think you'll know best whether or not this 
was fixed and should be able to easily close the PR if it was. 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=17583 
State-Changed-From-To: open->closed 
State-Changed-By: iedowse 
State-Changed-When: Sat Jun 23 13:43:21 PDT 2001 
State-Changed-Why:  

My analysis in the PR wasn't correct; Julian found that the code 
path I suggested couldn't occur. However the patch did cure the 
panics, so the real problem is possibly a more complex situation. 

The machine in question is no longer in service and the patch 
has been committed and MFC'd, so there's no point in keeping the 
PR open any longer. 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=17583 
>Unformatted:
