summaryrefslogtreecommitdiff
path: root/sys/dev/usb/net/if_cdceem.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/usb/net/if_cdceem.c')
-rw-r--r--sys/dev/usb/net/if_cdceem.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/sys/dev/usb/net/if_cdceem.c b/sys/dev/usb/net/if_cdceem.c
index ea92670e8f95..8bf6b041e4c2 100644
--- a/sys/dev/usb/net/if_cdceem.c
+++ b/sys/dev/usb/net/if_cdceem.c
@@ -426,9 +426,10 @@ cdceem_handle_data(struct usb_xfer *xfer, uint16_t hdr, int *offp)
struct usb_ether *ue;
struct ifnet *ifp;
struct mbuf *m;
- int actlen, off;
uint32_t computed_crc, received_crc;
- uint16_t pktlen;
+ int pktlen;
+ int actlen;
+ int off;
off = *offp;
sc = usbd_xfer_softc(xfer);
@@ -442,7 +443,7 @@ cdceem_handle_data(struct usb_xfer *xfer, uint16_t hdr, int *offp)
(hdr & CDCEEM_DATA_CRC) ? "valid" : "absent",
pktlen);
- if (pktlen < ETHER_HDR_LEN) {
+ if (pktlen < (ETHER_HDR_LEN + 4)) {
CDCEEM_WARN(sc,
"bad ethernet frame length %d, should be at least %d",
pktlen, ETHER_HDR_LEN);
@@ -466,6 +467,14 @@ cdceem_handle_data(struct usb_xfer *xfer, uint16_t hdr, int *offp)
}
pktlen -= 4; /* Subtract the CRC. */
+
+ if (pktlen > m->m_len) {
+ CDCEEM_WARN(sc, "buffer too small %d vs %d bytes",
+ pktlen, m->m_len);
+ if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
+ m_freem(m);
+ return;
+ }
usbd_copy_out(pc, off, mtod(m, uint8_t *), pktlen);
off += pktlen;
@@ -512,7 +521,7 @@ cdceem_bulk_read_callback(struct usb_xfer *xfer, usb_error_t usb_error)
pc = usbd_xfer_get_frame(xfer, 0);
off = 0;
- while (off < actlen) {
+ while ((off + sizeof(hdr)) <= actlen) {
usbd_copy_out(pc, off, &hdr, sizeof(hdr));
CDCEEM_DEBUG(sc, "hdr = %#x", hdr);
off += sizeof(hdr);