diff options
| author | mrg <mrg@NetBSD.org> | 2019-08-11 01:04:33 +0000 |
|---|---|---|
| committer | mrg <mrg@NetBSD.org> | 2019-08-11 01:04:33 +0000 |
| commit | 3fdca61dbda7dde0930b3deba73bec6b96fe0701 (patch) | |
| tree | 864645f367ce585757fc8782491e221247ca78db /sys/dev/usb | |
| parent | 2e5429fbcf0645d661fabe904cb94861c7fd8f60 (diff) | |
in tx_prepare callback make sure to reject any mbuf that is larger
than can fit in the buffer. done at the driver and not usbnet
layer because the driver knows how much beyond the mbuf data needs
to be sent (headers and trailers.)
axen(4) had a KASSERT() for this condition, but there's no
invariant here we can check so it's best as an error return.
XXX: only tested on these drivers, needs to be copied to udav, smsc
and urndis after testing as well as the not commited conversions.
Diffstat (limited to 'sys/dev/usb')
| -rw-r--r-- | sys/dev/usb/if_axe.c | 79 | ||||
| -rw-r--r-- | sys/dev/usb/if_axen.c | 11 | ||||
| -rw-r--r-- | sys/dev/usb/if_cdce.c | 22 | ||||
| -rw-r--r-- | sys/dev/usb/if_ure.c | 10 |
4 files changed, 65 insertions, 57 deletions
diff --git a/sys/dev/usb/if_axe.c b/sys/dev/usb/if_axe.c index a8e7ccc023b..2937b9d89e8 100644 --- a/sys/dev/usb/if_axe.c +++ b/sys/dev/usb/if_axe.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_axe.c,v 1.109 2019/08/10 02:17:36 mrg Exp $ */ +/* $NetBSD: if_axe.c,v 1.110 2019/08/11 01:04:33 mrg Exp $ */ /* $OpenBSD: if_axe.c,v 1.137 2016/04/13 11:03:37 mpi Exp $ */ /* @@ -87,7 +87,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_axe.c,v 1.109 2019/08/10 02:17:36 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_axe.c,v 1.110 2019/08/11 01:04:33 mrg Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -261,16 +261,16 @@ void axe_attach(device_t, device_t, void *); CFATTACH_DECL_NEW(axe, sizeof(struct axe_softc), axe_match, axe_attach, usbnet_detach, usbnet_activate); -static void axe_stop_cb(struct ifnet *, int); -static int axe_ioctl_cb(struct ifnet *, u_long, void *); +static void axe_stop(struct ifnet *, int); +static int axe_ioctl(struct ifnet *, u_long, void *); static int axe_init(struct ifnet *); static usbd_status axe_mii_read_reg(struct usbnet *, int, int, uint16_t *); static usbd_status axe_mii_write_reg(struct usbnet *, int, int, uint16_t); -static void axe_mii_statchg_cb(struct ifnet *); -static void axe_rx_loop_cb(struct usbnet *, struct usbd_xfer *, - struct usbnet_chain *, uint32_t); -static unsigned axe_tx_prepare_cb(struct usbnet *, struct mbuf *, - struct usbnet_chain *); +static void axe_mii_statchg(struct ifnet *); +static void axe_rx_loop(struct usbnet *, struct usbd_xfer *, + struct usbnet_chain *, uint32_t); +static unsigned axe_tx_prepare(struct usbnet *, struct mbuf *, + struct usbnet_chain *); static void axe_ax88178_init(struct axe_softc *); static void axe_ax88772_init(struct axe_softc *); @@ -278,13 +278,13 @@ static void axe_ax88772a_init(struct axe_softc *); static void axe_ax88772b_init(struct axe_softc *); static struct usbnet_ops axe_ops = { - .uno_stop = axe_stop_cb, - .uno_ioctl = axe_ioctl_cb, + .uno_stop = axe_stop, + .uno_ioctl = axe_ioctl, .uno_read_reg = axe_mii_read_reg, .uno_write_reg = axe_mii_write_reg, - .uno_statchg = axe_mii_statchg_cb, - .uno_tx_prepare = axe_tx_prepare_cb, - .uno_rx_loop = axe_rx_loop_cb, + .uno_statchg = axe_mii_statchg, + .uno_tx_prepare = axe_tx_prepare, + .uno_rx_loop = axe_rx_loop, .uno_init = axe_init, }; @@ -372,7 +372,7 @@ axe_mii_write_reg(struct usbnet *un, int phy, int reg, uint16_t val) } static void -axe_mii_statchg_cb(struct ifnet *ifp) +axe_mii_statchg(struct ifnet *ifp) { AXEHIST_FUNC(); AXEHIST_CALLED(); @@ -1016,8 +1016,8 @@ axe_attach(device_t parent, device_t self, void *aux) } static void -axe_rx_loop_cb(struct usbnet * un, struct usbd_xfer *xfer, - struct usbnet_chain *c, uint32_t total_len) +axe_rx_loop(struct usbnet * un, struct usbd_xfer *xfer, + struct usbnet_chain *c, uint32_t total_len) { AXEHIST_FUNC(); AXEHIST_CALLED(); struct axe_softc * const sc = usbnet_softc(un); @@ -1161,45 +1161,46 @@ axe_rx_loop_cb(struct usbnet * un, struct usbd_xfer *xfer, } static unsigned -axe_tx_prepare_cb(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) +axe_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) { AXEHIST_FUNC(); AXEHIST_CALLED(); + struct axe_sframe_hdr hdr, tlr; + size_t hdr_len = 0, tlr_len = 0; int length, boundary; usbnet_isowned_tx(un); - /* - * Copy the mbuf data into a contiguous buffer, leaving two - * bytes at the beginning to hold the frame length. - */ if (AXE_IS_178_FAMILY(un)) { - struct axe_sframe_hdr hdr; - + /* + * Copy the mbuf data into a contiguous buffer, leaving two + * bytes at the beginning to hold the frame length. + */ boundary = (un->un_udev->ud_speed == USB_SPEED_HIGH) ? 512 : 64; hdr.len = htole16(m->m_pkthdr.len); hdr.ilen = ~hdr.len; + hdr_len = sizeof(hdr); - memcpy(c->unc_buf, &hdr, sizeof(hdr)); - length = sizeof(hdr); - - m_copydata(m, 0, m->m_pkthdr.len, c->unc_buf + length); - length += m->m_pkthdr.len; + length = hdr_len + m->m_pkthdr.len; if ((length % boundary) == 0) { - hdr.len = 0x0000; - hdr.ilen = 0xffff; - memcpy(c->unc_buf + length, &hdr, sizeof(hdr)); - length += sizeof(hdr); + tlr.len = 0x0000; + tlr.ilen = 0xffff; + tlr_len = sizeof(tlr); } DPRINTFN(20, "length %jx m_pkthdr.len %jx hdrsize %#jx", length, m->m_pkthdr.len, sizeof(hdr), 0); - } else { - m_copydata(m, 0, m->m_pkthdr.len, c->unc_buf); - length = m->m_pkthdr.len; - DPRINTFN(20, "length %jx", length, 0, 0, 0); } + length = hdr_len + m->m_pkthdr.len + tlr_len; + if (length > un->un_tx_bufsz) + return 0; + + if (hdr_len) + memcpy(c->unc_buf, &hdr, hdr_len); + m_copydata(m, 0, m->m_pkthdr.len, c->unc_buf + hdr_len); + if (tlr_len) + memcpy(c->unc_buf + length, &tlr, tlr_len); return length; } @@ -1365,7 +1366,7 @@ axe_init(struct ifnet *ifp) } static int -axe_ioctl_cb(struct ifnet *ifp, u_long cmd, void *data) +axe_ioctl(struct ifnet *ifp, u_long cmd, void *data) { struct usbnet * const un = ifp->if_softc; @@ -1382,7 +1383,7 @@ axe_ioctl_cb(struct ifnet *ifp, u_long cmd, void *data) } static void -axe_stop_cb(struct ifnet *ifp, int disable) +axe_stop(struct ifnet *ifp, int disable) { struct usbnet * const un = ifp->if_softc; diff --git a/sys/dev/usb/if_axen.c b/sys/dev/usb/if_axen.c index 23c6219c7d9..1e4c3053ade 100644 --- a/sys/dev/usb/if_axen.c +++ b/sys/dev/usb/if_axen.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_axen.c,v 1.59 2019/08/10 02:17:36 mrg Exp $ */ +/* $NetBSD: if_axen.c,v 1.60 2019/08/11 01:04:33 mrg Exp $ */ /* $OpenBSD: if_axen.c,v 1.3 2013/10/21 10:10:22 yuo Exp $ */ /* @@ -23,7 +23,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_axen.c,v 1.59 2019/08/10 02:17:36 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_axen.c,v 1.60 2019/08/11 01:04:33 mrg Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -863,6 +863,10 @@ axen_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) usbnet_isowned_tx(un); + length = m->m_pkthdr.len + sizeof(hdr); + if (length > un->un_tx_bufsz) + return 0; + /* XXX Is this needed? wMaxPacketSize? */ switch (un->un_udev->ud_speed) { case USB_SPEED_SUPER: @@ -876,9 +880,6 @@ axen_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) break; } - length = m->m_pkthdr.len + sizeof(hdr); - KASSERT(length <= un->un_tx_bufsz); - hdr.plen = htole32(m->m_pkthdr.len); hdr.gso = (m->m_pkthdr.csum_flags & M_CSUM_TSOv4) ? diff --git a/sys/dev/usb/if_cdce.c b/sys/dev/usb/if_cdce.c index 4c8d9d7ce28..5d1132ad463 100644 --- a/sys/dev/usb/if_cdce.c +++ b/sys/dev/usb/if_cdce.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_cdce.c,v 1.61 2019/08/10 02:17:36 mrg Exp $ */ +/* $NetBSD: if_cdce.c,v 1.62 2019/08/11 01:04:33 mrg Exp $ */ /* * Copyright (c) 1997, 1998, 1999, 2000-2003 Bill Paul <wpaul@windriver.com> @@ -40,7 +40,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_cdce.c,v 1.61 2019/08/10 02:17:36 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_cdce.c,v 1.62 2019/08/11 01:04:33 mrg Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -295,19 +295,25 @@ cdce_rx_loop(struct usbnet * un, struct usbd_xfer *xfer, static unsigned cdce_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) { - int extra = 0; + /* Zaurus wants a 32-bit CRC appended to every frame */ + uint32_t crc; + unsigned extra = 0; + unsigned length; usbnet_isowned_tx(un); + if (un->un_flags & CDCE_ZAURUS) + extra = sizeof(crc); + + length = m->m_pkthdr.len + extra; + if (length > un->un_tx_bufsz) + return 0; + m_copydata(m, 0, m->m_pkthdr.len, c->unc_buf); if (un->un_flags & CDCE_ZAURUS) { - /* Zaurus wants a 32-bit CRC appended to every frame */ - uint32_t crc; - crc = htole32(~ether_crc32_le(c->unc_buf, m->m_pkthdr.len)); memcpy(c->unc_buf + m->m_pkthdr.len, &crc, sizeof(crc)); - extra = sizeof(crc); } - return m->m_pkthdr.len + extra; + return length; } diff --git a/sys/dev/usb/if_ure.c b/sys/dev/usb/if_ure.c index 99faf3ae6f7..b4e6144adb5 100644 --- a/sys/dev/usb/if_ure.c +++ b/sys/dev/usb/if_ure.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_ure.c,v 1.21 2019/08/10 02:17:36 mrg Exp $ */ +/* $NetBSD: if_ure.c,v 1.22 2019/08/11 01:04:33 mrg Exp $ */ /* $OpenBSD: if_ure.c,v 1.10 2018/11/02 21:32:30 jcs Exp $ */ /*- @@ -30,7 +30,7 @@ /* RealTek RTL8152/RTL8153 10/100/Gigabit USB Ethernet device */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_ure.c,v 1.21 2019/08/10 02:17:36 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_ure.c,v 1.22 2019/08/11 01:04:33 mrg Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -1066,6 +1066,9 @@ ure_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) usbnet_isowned_tx(un); + if (m->m_pkthdr.len + sizeof(txhdr) > un->un_tx_bufsz) + return 0; + /* header */ txhdr.ure_pktlen = htole32(m->m_pkthdr.len | URE_TXPKT_TX_FS | URE_TXPKT_TX_LS); @@ -1078,9 +1081,6 @@ ure_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) m_copydata(m, 0, m->m_pkthdr.len, buf); frm_len += m->m_pkthdr.len; - if (__predict_false(c->unc_xfer == NULL)) - return EIO; /* XXX plugged out or down */ - DPRINTFN(2, ("tx %d bytes\n", frm_len)); return frm_len; |
