From frank@exit.com  Sun Feb 20 20:12:56 2005
Return-Path: <frank@exit.com>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 1AA5316A521
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 20 Feb 2005 20:12:56 +0000 (GMT)
Received: from tinker.exit.com (tinker.exit.com [206.223.0.1])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 6E72043D41
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 20 Feb 2005 20:12:55 +0000 (GMT)
	(envelope-from frank@exit.com)
Received: from realtime.exit.com (realtime [206.223.0.5])
	by tinker.exit.com (8.13.1/8.13.1) with ESMTP id j1KKCqpT085075
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 20 Feb 2005 12:12:54 -0800 (PST)
	(envelope-from frank@exit.com)
Message-Id: <1108930374.0@realtime.exit.com>
Date: Sun, 20 Feb 2005 12:12:54 -0800
From: "Frank Mayhar" <frank@exit.com>
To: "FreeBSD gnats submit" <FreeBSD-gnats-submit@freebsd.org>
Subject: Reusing freed memory in if_bfe.c
X-Send-Pr-Version: gtk-send-pr 0.4.4 
X-GNATS-Notify:

>Number:         77804
>Category:       kern
>Synopsis:       [patch] Fix reusing freed memory in if_bfe.c in 6-CURRENT
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Feb 20 20:20:07 GMT 2005
>Closed-Date:    Thu Mar 17 14:08:53 GMT 2005
>Last-Modified:  Thu Mar 17 14:08:53 GMT 2005
>Originator:     Frank Mayhar
>Release:        FreeBSD 6.0-CURRENT
>Organization:
Exit Consulting 
>Environment:


FreeBSD lap 6.0-CURRENT FreeBSD 6.0-CURRENT #15: Sat Feb 19 18:46:46 PST 2005     frank@fw94:/home/obj/usr/src/sys/AUTON  i386



>Description:


In my recent hunt for my hard hang, I ran into a panic in
bfe_intr() in which it was dereferencing a freed dmamap
entry.  It turns out that doing an "ifconfig bfe0 down" forces
a call to bfe_stop(), which destroys the ring buffer dmamaps.
This is bad, since they are never recreated.

The fix (patch is attached) is to not destroy the dmamaps in
bfe_rx_ring_free()/bfe_tx_ring_free(), since they will be reused.
Instead, destroy them in the detach routine.  It turned out that
the detach routine was already destroying the tx ring buffer
dmamaps, but not the rx ones.

Patch follows.


>How-To-Repeat:





>Fix:


--- bfe-bug.diff begins here ---
Index: sys/dev/bfe/if_bfe.c
===================================================================
RCS file: /cvs/repos/src/sys/dev/bfe/if_bfe.c,v
retrieving revision 1.20
diff -u -r1.20 if_bfe.c
--- sys/dev/bfe/if_bfe.c	9 Jan 2005 19:57:55 -0000	1.20
+++ sys/dev/bfe/if_bfe.c	20 Feb 2005 19:56:00 -0000
@@ -541,8 +541,6 @@
 			sc->bfe_tx_ring[i].bfe_mbuf = NULL;
 			bus_dmamap_unload(sc->bfe_tag,
 					sc->bfe_tx_ring[i].bfe_map);
-			bus_dmamap_destroy(sc->bfe_tag,
-					sc->bfe_tx_ring[i].bfe_map);
 		}
 	}
 	bzero(sc->bfe_tx_list, BFE_TX_LIST_SIZE);
@@ -560,15 +558,12 @@
 			sc->bfe_rx_ring[i].bfe_mbuf = NULL;
 			bus_dmamap_unload(sc->bfe_tag,
 					sc->bfe_rx_ring[i].bfe_map);
-			bus_dmamap_destroy(sc->bfe_tag,
-					sc->bfe_rx_ring[i].bfe_map);
 		}
 	}
 	bzero(sc->bfe_rx_list, BFE_RX_LIST_SIZE);
 	bus_dmamap_sync(sc->bfe_rx_tag, sc->bfe_rx_map, BUS_DMASYNC_PREREAD);
 }
 
-
 static int
 bfe_list_rx_init(struct bfe_softc *sc)
 {
@@ -975,6 +970,8 @@
 		for(i = 0; i < BFE_TX_LIST_CNT; i++) {
 			bus_dmamap_destroy(sc->bfe_tag,
 			    sc->bfe_tx_ring[i].bfe_map);
+			bus_dmamap_destroy(sc->bfe_tag,
+			    sc->bfe_rx_ring[i].bfe_map);
 		}
 		bus_dma_tag_destroy(sc->bfe_tag);
 		sc->bfe_tag = NULL;
--- bfe-bug.diff ends here ---



>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-i386->freebsd-bugs 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Thu Mar 10 21:11:02 GMT 2005 
Responsible-Changed-Why:  
Fix up synopsis and Release; reclassify as kern since it does not 
seem to be hardware-specific. 

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

From: Tai-hwa Liang <avatar@mmlab.cse.yzu.edu.tw>
To: freebsd-gnats-submit@FreeBSD.org
Cc: frank@exit.com
Subject: Re: kern/77804: [patch] Fix reusing freed memory in if_bfe.c in
 6-CURRENT
Date: Sun, 13 Mar 2005 00:01:55 +0800 (CST)

 Hi Frank,
 
    After discussed with dmlb@ and sam@, we agree that your patch is
 needed; however, would you please test following patch again since
 this one makes a different assumption on the number of TX/RX descriptors?
 
 --- if_bfe.c.orig	Mon Jan 10 03:57:55 2005
 +++ if_bfe.c	Sat Mar 12 23:52:10 2005
 @@ -541,8 +541,6 @@
   			sc->bfe_tx_ring[i].bfe_mbuf = NULL;
   			bus_dmamap_unload(sc->bfe_tag,
   					sc->bfe_tx_ring[i].bfe_map);
 -			bus_dmamap_destroy(sc->bfe_tag,
 -					sc->bfe_tx_ring[i].bfe_map);
   		}
   	}
   	bzero(sc->bfe_tx_list, BFE_TX_LIST_SIZE);
 @@ -560,15 +558,12 @@
   			sc->bfe_rx_ring[i].bfe_mbuf = NULL;
   			bus_dmamap_unload(sc->bfe_tag,
   					sc->bfe_rx_ring[i].bfe_map);
 -			bus_dmamap_destroy(sc->bfe_tag,
 -					sc->bfe_rx_ring[i].bfe_map);
   		}
   	}
   	bzero(sc->bfe_rx_list, BFE_RX_LIST_SIZE);
   	bus_dmamap_sync(sc->bfe_rx_tag, sc->bfe_rx_map, BUS_DMASYNC_PREREAD);
   }
 
 -
   static int
   bfe_list_rx_init(struct bfe_softc *sc)
   {
 @@ -975,6 +970,10 @@
   		for(i = 0; i < BFE_TX_LIST_CNT; i++) {
   			bus_dmamap_destroy(sc->bfe_tag,
   			    sc->bfe_tx_ring[i].bfe_map);
 +		}
 +		for(i = 0; i < BFE_RX_LIST_CNT; i++) {
 +			bus_dmamap_destroy(sc->bfe_tag,
 +			    sc->bfe_rx_ring[i].bfe_map);
   		}
   		bus_dma_tag_destroy(sc->bfe_tag);
   		sc->bfe_tag = NULL;
State-Changed-From-To: open->closed 
State-Changed-By: avatar 
State-Changed-When: Thu Mar 17 14:03:57 GMT 2005 
State-Changed-Why:  
Updated patch has been committed to HEAD. 

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