- Fix mbuf/node leakage in drivers' raw_xmit().

- For ural(4):
  o  Fix node leakage in ural_start(), if ural_tx_mgt() fails.
  o  Fix mbuf leakage in ural_tx_{mgt,data}(), if usbd_transfer() fails.
  o  In ural_tx_{mgt,data}(), set ural_tx_data.{m,ni} to NULL, if
     usbd_transfer() fails, so they will not be freed again in ural_stop().

Approved by:	sam (mentor)
This commit is contained in:
Sepherosa Ziehau 2007-04-19 13:09:57 +00:00
parent f1f73e5718
commit b03cfe2396
4 changed files with 39 additions and 14 deletions

View File

@ -5838,6 +5838,7 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
struct ath_buf *bf;
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid) {
ieee80211_free_node(ni);
m_freem(m);
return ENETDOWN;
}
@ -5854,6 +5855,7 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
__func__);
sc->sc_stats.ast_tx_qstop++;
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
ieee80211_free_node(ni);
m_freem(m);
return ENOBUFS;
}

View File

@ -1716,8 +1716,10 @@ rt2560_tx_raw(struct rt2560_softc *sc, struct mbuf *m0,
rate = params->ibp_rate0 & IEEE80211_RATE_VAL;
/* XXX validate */
if (rate == 0)
if (rate == 0) {
m_freem(m0);
return EINVAL;
}
error = bus_dmamap_load_mbuf_sg(sc->prioq.data_dmat, data->map, m0,
segs, &nsegs, 0);
@ -2782,11 +2784,15 @@ rt2560_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
/* prevent management frames from being sent if we're not ready */
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
RAL_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return ENETDOWN;
}
if (sc->prioq.queued >= RT2560_PRIO_RING_COUNT) {
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
RAL_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return ENOBUFS; /* XXX */
}

View File

@ -1222,8 +1222,12 @@ ural_tx_mgt(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
ural_txeof);
error = usbd_transfer(data->xfer);
if (error != USBD_NORMAL_COMPLETION && error != USBD_IN_PROGRESS)
if (error != USBD_NORMAL_COMPLETION && error != USBD_IN_PROGRESS) {
m_freem(m0);
data->m = NULL;
data->ni = NULL;
return error;
}
sc->tx_queued++;
@ -1246,8 +1250,10 @@ ural_tx_raw(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
rate = params->ibp_rate0 & IEEE80211_RATE_VAL;
/* XXX validate */
if (rate == 0)
if (rate == 0) {
m_freem(m0);
return EINVAL;
}
if (bpf_peers_present(sc->sc_drvbpf)) {
struct ural_tx_radiotap_header *tap = &sc->sc_txtap;
@ -1379,8 +1385,12 @@ ural_tx_data(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
ural_txeof);
error = usbd_transfer(data->xfer);
if (error != USBD_NORMAL_COMPLETION && error != USBD_IN_PROGRESS)
if (error != USBD_NORMAL_COMPLETION && error != USBD_IN_PROGRESS) {
m_freem(m0);
data->m = NULL;
data->ni = NULL;
return error;
}
sc->tx_queued++;
@ -1411,9 +1421,10 @@ ural_start(struct ifnet *ifp)
if (bpf_peers_present(ic->ic_rawbpf))
bpf_mtap(ic->ic_rawbpf, m0);
if (ural_tx_mgt(sc, m0, ni) != 0)
if (ural_tx_mgt(sc, m0, ni) != 0) {
ieee80211_free_node(ni);
break;
}
} else {
if (ic->ic_state != IEEE80211_S_RUN)
break;
@ -2310,10 +2321,15 @@ ural_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
struct ural_softc *sc = ifp->if_softc;
/* prevent management frames from being sent if we're not ready */
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
m_freem(m);
ieee80211_free_node(ni);
return ENETDOWN;
}
if (sc->tx_queued >= RAL_TX_LIST_COUNT) {
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
m_freem(m);
ieee80211_free_node(ni);
return EIO;
}

View File

@ -1093,9 +1093,6 @@ wi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m0,
k = ieee80211_crypto_encap(ic, ni, m0);
if (k == NULL) {
if (ni != NULL)
ieee80211_free_node(ni);
m_freem(m0);
rc = ENOMEM;
goto out;
}
@ -1116,16 +1113,20 @@ wi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m0,
frmhdr.wi_dat_len = htole16(m0->m_pkthdr.len);
if (IFF_DUMPPKTS(ifp))
wi_dump_pkt(&frmhdr, NULL, -1);
if (ni != NULL)
ieee80211_free_node(ni);
rc = wi_start_tx(ifp, &frmhdr, m0);
if (rc)
if (wi_start_tx(ifp, &frmhdr, m0) < 0) {
m0 = NULL;
rc = EIO;
goto out;
}
m0 = NULL;
sc->sc_txnext = cur = (cur + 1) % sc->sc_ntxbuf;
out:
WI_UNLOCK(sc);
if (m0 != NULL)
m_freem(m0);
ieee80211_free_node(ni);
return rc;
}