Module Name: src Committed By: mrg Date: Sun Aug 11 01:04:33 UTC 2019
Modified Files: src/sys/dev/usb: if_axe.c if_axen.c if_cdce.c if_ure.c Log Message: 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. To generate a diff of this commit: cvs rdiff -u -r1.109 -r1.110 src/sys/dev/usb/if_axe.c cvs rdiff -u -r1.59 -r1.60 src/sys/dev/usb/if_axen.c cvs rdiff -u -r1.61 -r1.62 src/sys/dev/usb/if_cdce.c cvs rdiff -u -r1.21 -r1.22 src/sys/dev/usb/if_ure.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/usb/if_axe.c diff -u src/sys/dev/usb/if_axe.c:1.109 src/sys/dev/usb/if_axe.c:1.110 --- src/sys/dev/usb/if_axe.c:1.109 Sat Aug 10 02:17:36 2019 +++ src/sys/dev/usb/if_axe.c Sun Aug 11 01:04:33 2019 @@ -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 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 } 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 sel } 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, struc } 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 c } static void -axe_stop_cb(struct ifnet *ifp, int disable) +axe_stop(struct ifnet *ifp, int disable) { struct usbnet * const un = ifp->if_softc; Index: src/sys/dev/usb/if_axen.c diff -u src/sys/dev/usb/if_axen.c:1.59 src/sys/dev/usb/if_axen.c:1.60 --- src/sys/dev/usb/if_axen.c:1.59 Sat Aug 10 02:17:36 2019 +++ src/sys/dev/usb/if_axen.c Sun Aug 11 01:04:33 2019 @@ -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, struc 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, struc 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) ? Index: src/sys/dev/usb/if_cdce.c diff -u src/sys/dev/usb/if_cdce.c:1.61 src/sys/dev/usb/if_cdce.c:1.62 --- src/sys/dev/usb/if_cdce.c:1.61 Sat Aug 10 02:17:36 2019 +++ src/sys/dev/usb/if_cdce.c Sun Aug 11 01:04:33 2019 @@ -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 <wp...@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 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; } Index: src/sys/dev/usb/if_ure.c diff -u src/sys/dev/usb/if_ure.c:1.21 src/sys/dev/usb/if_ure.c:1.22 --- src/sys/dev/usb/if_ure.c:1.21 Sat Aug 10 02:17:36 2019 +++ src/sys/dev/usb/if_ure.c Sun Aug 11 01:04:33 2019 @@ -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 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 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;