diff options
author | damien <damien@FreeBSD.org> | 2005-06-29 17:54:01 +0000 |
---|---|---|
committer | damien <damien@FreeBSD.org> | 2005-06-29 17:54:01 +0000 |
commit | 5240ace1db4d06e71e602d7f87cfa9d4724535b8 (patch) | |
tree | 16e8899beb7f746fde6a7b131b3f7552342f9672 /sys/dev/ral | |
parent | 6886350a3073ef04cfc52d90da8dc7628663aceb (diff) | |
download | FreeBSD-src-5240ace1db4d06e71e602d7f87cfa9d4724535b8.zip FreeBSD-src-5240ace1db4d06e71e602d7f87cfa9d4724535b8.tar.gz |
o Fix a write mbuf-after-free bug. The duration field of the 802.11 header
was written in the old fragmented mbuf chain instead of the defragmented
one. Thus, the duration field of outgoing frames was incorrect.
o Only call m_defrag() if the mbuf fragmentation threshold is greater
than what is currently supported by the driver.
Reviewed by: silby (mentor)
Approved by: re (scottl)
Diffstat (limited to 'sys/dev/ral')
-rw-r--r-- | sys/dev/ral/if_ral.c | 32 |
1 files changed, 23 insertions, 9 deletions
diff --git a/sys/dev/ral/if_ral.c b/sys/dev/ral/if_ral.c index 2a25f92..9e6cf74 100644 --- a/sys/dev/ral/if_ral.c +++ b/sys/dev/ral/if_ral.c @@ -1971,22 +1971,36 @@ ral_tx_data(struct ral_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) data = &sc->txq.data[sc->txq.cur_encrypt]; desc = &sc->txq.desc[sc->txq.cur_encrypt]; - mnew = m_defrag(m0, M_DONTWAIT); - if (mnew == NULL) { - device_printf(sc->sc_dev, "could not defragment mbuf\n"); - m_freem(m0); - return ENOMEM; - } - m0 = mnew; - error = bus_dmamap_load_mbuf_sg(sc->txq.data_dmat, data->map, m0, segs, &nsegs, 0); - if (error != 0) { + if (error != 0 && error != EFBIG) { device_printf(sc->sc_dev, "could not map mbuf (error %d)\n", error); m_freem(m0); return error; } + if (error != 0) { + mnew = m_defrag(m0, M_DONTWAIT); + if (mnew == NULL) { + device_printf(sc->sc_dev, + "could not defragment mbuf\n"); + m_freem(m0); + return ENOBUFS; + } + m0 = mnew; + + error = bus_dmamap_load_mbuf_sg(sc->txq.data_dmat, data->map, + m0, segs, &nsegs, 0); + if (error != 0) { + device_printf(sc->sc_dev, + "could not map mbuf (error %d)\n", error); + m_freem(m0); + return error; + } + + /* packet header may have moved, reset our local pointer */ + wh = mtod(m0, struct ieee80211_frame *); + } if (sc->sc_drvbpf != NULL) { struct ral_tx_radiotap_header *tap = &sc->sc_txtap; |