DF-0997 / fix.diff
diff --git a/sys/bus/u4b/wlan/if_rum.c b/sys/bus/u4b/wlan/if_rum.c @@ -1218,7 +1218,31 @@ } /* finalize mbuf */ - m->m_pkthdr.len = m->m_len = (flags >> 16) & 0xfff; + { + unsigned int pktlen = (flags >> 16) & 0xfff; + + /* + * The RX descriptor length field is device-controlled. + * A malicious or faulty USB device can advertise a length + * larger than what we actually received (and larger than + * the mbuf cluster), which would cause subsequent + * net80211/BPF readers to walk off the cluster into + * kernel heap. Clamp to the host-controller-bounded + * actlen-derived `len` and drop if bogus. See DF-0997. + */ + if (pktlen > (unsigned int)len || pktlen > MCLBYTES) { + DPRINTF("%s: bogus rx length %u (> %d)\n", + device_get_nameunit(sc->sc_dev), pktlen, len); +#if defined(__DragonFly__) + ++ic->ic_ierrors; +#else + counter_u64_add(ic->ic_ierrors, 1); +#endif + m_freem(m); + goto tr_setup; + } + m->m_pkthdr.len = m->m_len = pktlen; + } if (ieee80211_radiotap_active(ic)) { struct rum_rx_radiotap_header *tap = &sc->sc_rxtap; |