Add missing range checks when receiving USB ethernet packets.
Found by: Ilja Van Sprundel, IOActive MFC after: 3 days Sponsored by: Mellanox Technologies
This commit is contained in:
parent
bc8e281082
commit
9c847ffd74
@ -427,9 +427,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);
|
||||
@ -443,7 +444,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);
|
||||
@ -467,6 +468,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;
|
||||
|
||||
@ -513,7 +522,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);
|
||||
|
@ -1169,9 +1169,9 @@ muge_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
struct ifnet *ifp = uether_getifp(ue);
|
||||
struct mbuf *m;
|
||||
struct usb_page_cache *pc;
|
||||
uint16_t pktlen;
|
||||
uint32_t rx_cmd_a, rx_cmd_b;
|
||||
uint16_t rx_cmd_c;
|
||||
int pktlen;
|
||||
int off;
|
||||
int actlen;
|
||||
|
||||
@ -1249,7 +1249,14 @@ muge_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
1);
|
||||
goto tr_setup;
|
||||
}
|
||||
|
||||
if (pktlen > m->m_len) {
|
||||
muge_dbg_printf(sc,
|
||||
"buffer too small %d vs %d bytes",
|
||||
pktlen, m->m_len);
|
||||
if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
|
||||
m_freem(m);
|
||||
goto tr_setup;
|
||||
}
|
||||
usbd_copy_out(pc, off, mtod(m, uint8_t *),
|
||||
pktlen);
|
||||
|
||||
|
@ -955,7 +955,7 @@ smsc_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
struct mbuf *m;
|
||||
struct usb_page_cache *pc;
|
||||
uint32_t rxhdr;
|
||||
uint16_t pktlen;
|
||||
int pktlen;
|
||||
int off;
|
||||
int actlen;
|
||||
|
||||
@ -981,6 +981,9 @@ smsc_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
/* The frame header is always aligned on a 4 byte boundary */
|
||||
off = ((off + 0x3) & ~0x3);
|
||||
|
||||
if ((off + sizeof(rxhdr)) > actlen)
|
||||
goto tr_setup;
|
||||
|
||||
usbd_copy_out(pc, off, &rxhdr, sizeof(rxhdr));
|
||||
off += (sizeof(rxhdr) + ETHER_ALIGN);
|
||||
rxhdr = le32toh(rxhdr);
|
||||
@ -1009,7 +1012,13 @@ smsc_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
|
||||
goto tr_setup;
|
||||
}
|
||||
|
||||
if (pktlen > m->m_len) {
|
||||
smsc_dbg_printf(sc, "buffer too small %d vs %d bytes",
|
||||
pktlen, m->m_len);
|
||||
if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
|
||||
m_freem(m);
|
||||
goto tr_setup;
|
||||
}
|
||||
usbd_copy_out(pc, off, mtod(m, uint8_t *), pktlen);
|
||||
|
||||
/* Check if RX TCP/UDP checksumming is being offloaded */
|
||||
|
Loading…
x
Reference in New Issue
Block a user