when nfe_attach() fails, free all resources including

interrupt map, interrupt handler and dma maps.
Also prevent call to bus_dmamap_destroy() when bus_dmamap_create() failed.
The nfe_free_* routines assume, the map pointers are NULL but they
are actually undefined. Make the assumption true by making them NULL
in the error path of bus_dmamap_create().

All together, this fixes crashes when nfe_attach() fails.
ok martin@
This commit is contained in:
cegger 2009-03-01 13:34:10 +00:00
parent 87b8a8844f
commit 945fa6c58f
1 changed files with 21 additions and 6 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_nfe.c,v 1.41 2009/03/01 08:29:25 cegger Exp $ */ /* $NetBSD: if_nfe.c,v 1.42 2009/03/01 13:34:10 cegger Exp $ */
/* $OpenBSD: if_nfe.c,v 1.77 2008/02/05 16:52:50 brad Exp $ */ /* $OpenBSD: if_nfe.c,v 1.77 2008/02/05 16:52:50 brad Exp $ */
/*- /*-
@ -21,7 +21,7 @@
/* Driver for NVIDIA nForce MCP Fast Ethernet and Gigabit Ethernet */ /* Driver for NVIDIA nForce MCP Fast Ethernet and Gigabit Ethernet */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_nfe.c,v 1.41 2009/03/01 08:29:25 cegger Exp $"); __KERNEL_RCSID(0, "$NetBSD: if_nfe.c,v 1.42 2009/03/01 13:34:10 cegger Exp $");
#include "opt_inet.h" #include "opt_inet.h"
#include "bpfilter.h" #include "bpfilter.h"
@ -245,7 +245,7 @@ nfe_attach(device_t parent, device_t self, void *aux)
if (pci_intr_map(pa, &ih) != 0) { if (pci_intr_map(pa, &ih) != 0) {
aprint_error_dev(self, "could not map interrupt\n"); aprint_error_dev(self, "could not map interrupt\n");
return; goto fail;
} }
intrstr = pci_intr_string(pc, ih); intrstr = pci_intr_string(pc, ih);
@ -255,7 +255,7 @@ nfe_attach(device_t parent, device_t self, void *aux)
if (intrstr != NULL) if (intrstr != NULL)
aprint_normal(" at %s", intrstr); aprint_normal(" at %s", intrstr);
aprint_normal("\n"); aprint_normal("\n");
return; goto fail;
} }
aprint_normal_dev(self, "interrupting at %s\n", intrstr); aprint_normal_dev(self, "interrupting at %s\n", intrstr);
@ -345,7 +345,7 @@ nfe_attach(device_t parent, device_t self, void *aux)
*/ */
if (nfe_alloc_tx_ring(sc, &sc->txq) != 0) { if (nfe_alloc_tx_ring(sc, &sc->txq) != 0) {
aprint_error_dev(self, "could not allocate Tx ring\n"); aprint_error_dev(self, "could not allocate Tx ring\n");
return; goto fail;
} }
mutex_init(&sc->rxq.mtx, MUTEX_DEFAULT, IPL_NET); mutex_init(&sc->rxq.mtx, MUTEX_DEFAULT, IPL_NET);
@ -353,7 +353,7 @@ nfe_attach(device_t parent, device_t self, void *aux)
if (nfe_alloc_rx_ring(sc, &sc->rxq) != 0) { if (nfe_alloc_rx_ring(sc, &sc->rxq) != 0) {
aprint_error_dev(self, "could not allocate Rx ring\n"); aprint_error_dev(self, "could not allocate Rx ring\n");
nfe_free_tx_ring(sc, &sc->txq); nfe_free_tx_ring(sc, &sc->txq);
return; goto fail;
} }
ifp = &sc->sc_ethercom.ec_if; ifp = &sc->sc_ethercom.ec_if;
@ -416,6 +416,16 @@ nfe_attach(device_t parent, device_t self, void *aux)
aprint_error_dev(self, "couldn't establish power handler\n"); aprint_error_dev(self, "couldn't establish power handler\n");
else else
pmf_class_network_register(self, ifp); pmf_class_network_register(self, ifp);
return;
fail:
if (sc->sc_ih != NULL) {
pci_intr_disestablish(pc, sc->sc_ih);
sc->sc_ih = NULL;
}
if (memsize)
bus_space_unmap(sc->sc_memt, sc->sc_memh, memsize);
} }
void void
@ -1362,6 +1372,7 @@ nfe_alloc_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring)
if (error != 0) { if (error != 0) {
aprint_error_dev(sc->sc_dev, aprint_error_dev(sc->sc_dev,
"could not create desc DMA map\n"); "could not create desc DMA map\n");
ring->map = NULL;
goto fail; goto fail;
} }
@ -1430,6 +1441,7 @@ nfe_alloc_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring)
if (error != 0) { if (error != 0) {
aprint_error_dev(sc->sc_dev, aprint_error_dev(sc->sc_dev,
"could not create DMA map\n"); "could not create DMA map\n");
data->map = NULL;
goto fail; goto fail;
} }
MCLGET(data->m, M_DONTWAIT); MCLGET(data->m, M_DONTWAIT);
@ -1599,6 +1611,7 @@ nfe_jpool_alloc(struct nfe_softc *sc)
if (error != 0) { if (error != 0) {
aprint_error_dev(sc->sc_dev, aprint_error_dev(sc->sc_dev,
"could not create jumbo DMA map\n"); "could not create jumbo DMA map\n");
ring->jmap = NULL;
goto fail; goto fail;
} }
@ -1690,6 +1703,7 @@ nfe_alloc_tx_ring(struct nfe_softc *sc, struct nfe_tx_ring *ring)
if (error != 0) { if (error != 0) {
aprint_error_dev(sc->sc_dev, aprint_error_dev(sc->sc_dev,
"could not create desc DMA map\n"); "could not create desc DMA map\n");
ring->map = NULL;
goto fail; goto fail;
} }
@ -1726,6 +1740,7 @@ nfe_alloc_tx_ring(struct nfe_softc *sc, struct nfe_tx_ring *ring)
if (error != 0) { if (error != 0) {
aprint_error_dev(sc->sc_dev, aprint_error_dev(sc->sc_dev,
"could not create DMA map\n"); "could not create DMA map\n");
ring->data[i].map = NULL;
goto fail; goto fail;
} }
} }