Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/usb in tx_prepare callback make sure to reject any m...



details:   https://anonhg.NetBSD.org/src/rev/dee78a48f508
branches:  trunk
changeset: 1002687:dee78a48f508
user:      mrg <mrg%NetBSD.org@localhost>
date:      Sun Aug 11 01:04:33 2019 +0000

description:
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:

 sys/dev/usb/if_axe.c  |  79 +++++++++++++++++++++++++-------------------------
 sys/dev/usb/if_axen.c |  11 +++---
 sys/dev/usb/if_cdce.c |  22 +++++++++-----
 sys/dev/usb/if_ure.c  |  10 +++---
 4 files changed, 65 insertions(+), 57 deletions(-)

diffs (293 lines):

diff -r 9224c6271617 -r dee78a48f508 sys/dev/usb/if_axe.c
--- a/sys/dev/usb/if_axe.c      Sat Aug 10 23:47:13 2019 +0000
+++ b/sys/dev/usb/if_axe.c      Sun Aug 11 01:04:33 2019 +0000
@@ -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 @@
 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_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 @@
 }
 
 static void
-axe_mii_statchg_cb(struct ifnet *ifp)
+axe_mii_statchg(struct ifnet *ifp)
 {
        AXEHIST_FUNC(); AXEHIST_CALLED();
 
@@ -1016,8 +1016,8 @@
 }
 
 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 @@
 }
 
 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 @@
 }
 
 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 @@
 }
 
 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 -r 9224c6271617 -r dee78a48f508 sys/dev/usb/if_axen.c
--- a/sys/dev/usb/if_axen.c     Sat Aug 10 23:47:13 2019 +0000
+++ b/sys/dev/usb/if_axen.c     Sun Aug 11 01:04:33 2019 +0000
@@ -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 @@
 
        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 @@
                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 -r 9224c6271617 -r dee78a48f508 sys/dev/usb/if_cdce.c
--- a/sys/dev/usb/if_cdce.c     Sat Aug 10 23:47:13 2019 +0000
+++ b/sys/dev/usb/if_cdce.c     Sun Aug 11 01:04:33 2019 +0000
@@ -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@localhost>
@@ -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 @@
 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 -r 9224c6271617 -r dee78a48f508 sys/dev/usb/if_ure.c
--- a/sys/dev/usb/if_ure.c      Sat Aug 10 23:47:13 2019 +0000
+++ b/sys/dev/usb/if_ure.c      Sun Aug 11 01:04:33 2019 +0000
@@ -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 @@
 
        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 @@
        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;



Home | Main Index | Thread Index | Old Index