From a10c0e45748adcecd3a14ac96fd0f2b4cebed650 Mon Sep 17 00:00:00 2001 From: Mike Silbersack Date: Sun, 19 Oct 2003 23:05:19 +0000 Subject: [PATCH] Fix a problem where m_defrag would allocate a new mbuf to replace the chain passed into dc_encap, which dc_start was unaware of. This caused the old (now invalid) mbuf to be passed to BPF_MTAP. Spotted by: Kenjiro Cho --- sys/dev/dc/if_dc.c | 16 ++++++++-------- sys/pci/if_dc.c | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/sys/dev/dc/if_dc.c b/sys/dev/dc/if_dc.c index 603270361b3c..b120f439fe41 100644 --- a/sys/dev/dc/if_dc.c +++ b/sys/dev/dc/if_dc.c @@ -224,7 +224,7 @@ static void dc_acpi (device_t); #endif static struct dc_type *dc_devtype (device_t); static int dc_newbuf (struct dc_softc *, int, int); -static int dc_encap (struct dc_softc *, struct mbuf *); +static int dc_encap (struct dc_softc *, struct mbuf **); static void dc_pnic_rx_bug_war (struct dc_softc *, int); static int dc_rx_resync (struct dc_softc *); static void dc_rxeof (struct dc_softc *); @@ -3266,7 +3266,7 @@ dc_dma_map_txbuf(arg, segs, nseg, mapsize, error) * pointers to the fragment pointers. */ static int -dc_encap(struct dc_softc *sc, struct mbuf *m_head) +dc_encap(struct dc_softc *sc, struct mbuf **m_head) { struct mbuf *m; int error, idx, chainlen = 0; @@ -3283,15 +3283,15 @@ dc_encap(struct dc_softc *sc, struct mbuf *m_head) * by all packets, we'll m_defrag long chains so that they * do not use up the entire list, even if they would fit. */ - for (m = m_head; m != NULL; m = m->m_next) + for (m = *m_head; m != NULL; m = m->m_next) chainlen++; if ((chainlen > DC_TX_LIST_CNT / 4) || ((DC_TX_LIST_CNT - (chainlen + sc->dc_cdata.dc_tx_cnt)) < 6)) { - m = m_defrag(m_head, M_DONTWAIT); + m = m_defrag(*m_head, M_DONTWAIT); if (m == NULL) return (ENOBUFS); - m_head = m; + *m_head = m; } /* @@ -3301,12 +3301,12 @@ dc_encap(struct dc_softc *sc, struct mbuf *m_head) */ idx = sc->dc_cdata.dc_tx_prod; error = bus_dmamap_load_mbuf(sc->dc_mtag, sc->dc_cdata.dc_tx_map[idx], - m_head, dc_dma_map_txbuf, sc, 0); + *m_head, dc_dma_map_txbuf, sc, 0); if (error) return (error); if (sc->dc_cdata.dc_tx_err != 0) return (sc->dc_cdata.dc_tx_err); - sc->dc_cdata.dc_tx_chain[idx] = m_head; + sc->dc_cdata.dc_tx_chain[idx] = *m_head; bus_dmamap_sync(sc->dc_mtag, sc->dc_cdata.dc_tx_map[idx], BUS_DMASYNC_PREWRITE); bus_dmamap_sync(sc->dc_ltag, sc->dc_lmap, @@ -3362,7 +3362,7 @@ dc_start(struct ifnet *ifp) } } - if (dc_encap(sc, m_head)) { + if (dc_encap(sc, &m_head)) { IF_PREPEND(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; break; diff --git a/sys/pci/if_dc.c b/sys/pci/if_dc.c index 603270361b3c..b120f439fe41 100644 --- a/sys/pci/if_dc.c +++ b/sys/pci/if_dc.c @@ -224,7 +224,7 @@ static void dc_acpi (device_t); #endif static struct dc_type *dc_devtype (device_t); static int dc_newbuf (struct dc_softc *, int, int); -static int dc_encap (struct dc_softc *, struct mbuf *); +static int dc_encap (struct dc_softc *, struct mbuf **); static void dc_pnic_rx_bug_war (struct dc_softc *, int); static int dc_rx_resync (struct dc_softc *); static void dc_rxeof (struct dc_softc *); @@ -3266,7 +3266,7 @@ dc_dma_map_txbuf(arg, segs, nseg, mapsize, error) * pointers to the fragment pointers. */ static int -dc_encap(struct dc_softc *sc, struct mbuf *m_head) +dc_encap(struct dc_softc *sc, struct mbuf **m_head) { struct mbuf *m; int error, idx, chainlen = 0; @@ -3283,15 +3283,15 @@ dc_encap(struct dc_softc *sc, struct mbuf *m_head) * by all packets, we'll m_defrag long chains so that they * do not use up the entire list, even if they would fit. */ - for (m = m_head; m != NULL; m = m->m_next) + for (m = *m_head; m != NULL; m = m->m_next) chainlen++; if ((chainlen > DC_TX_LIST_CNT / 4) || ((DC_TX_LIST_CNT - (chainlen + sc->dc_cdata.dc_tx_cnt)) < 6)) { - m = m_defrag(m_head, M_DONTWAIT); + m = m_defrag(*m_head, M_DONTWAIT); if (m == NULL) return (ENOBUFS); - m_head = m; + *m_head = m; } /* @@ -3301,12 +3301,12 @@ dc_encap(struct dc_softc *sc, struct mbuf *m_head) */ idx = sc->dc_cdata.dc_tx_prod; error = bus_dmamap_load_mbuf(sc->dc_mtag, sc->dc_cdata.dc_tx_map[idx], - m_head, dc_dma_map_txbuf, sc, 0); + *m_head, dc_dma_map_txbuf, sc, 0); if (error) return (error); if (sc->dc_cdata.dc_tx_err != 0) return (sc->dc_cdata.dc_tx_err); - sc->dc_cdata.dc_tx_chain[idx] = m_head; + sc->dc_cdata.dc_tx_chain[idx] = *m_head; bus_dmamap_sync(sc->dc_mtag, sc->dc_cdata.dc_tx_map[idx], BUS_DMASYNC_PREWRITE); bus_dmamap_sync(sc->dc_ltag, sc->dc_lmap, @@ -3362,7 +3362,7 @@ dc_start(struct ifnet *ifp) } } - if (dc_encap(sc, m_head)) { + if (dc_encap(sc, &m_head)) { IF_PREPEND(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; break;