i386/77804: Reusing freed memory in if_bfe.c

Frank Mayhar frank at exit.com
Sun Feb 20 12:20:08 PST 2005


>Number:         77804
>Category:       i386
>Synopsis:       Reusing freed memory in if_bfe.c
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    freebsd-i386
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Feb 20 20:20:07 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     Frank Mayhar
>Release:        FreeBSD 4.11-STABLE i386
>Organization:
Exit Consulting 
>Environment:


FreeBSD lap 6.0-CURRENT FreeBSD 6.0-CURRENT #15: Sat Feb 19 18:46:46 PST 2005     frank at 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:
>Unformatted:


More information about the freebsd-i386 mailing list