Hi,

I updated the diff for axe(4) based on what Laurent
sent me. He says the patch breaks his axe(4).

I also added a comment to explain why it's done,
in areas where there's a status bit called RX_STATUS.

This is based on an issue I encountered with udav(4),
wherein despite having a valid status bit, the
frame length was bogus.

It's even more important that we test this on as much
USB adapters as possible.

Thanks to the users who are doing a good job at testing 
the diffs.

Index: src/sys/dev/usb/if_axe.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/if_axe.c,v
retrieving revision 1.105
diff -u -p -r1.105 if_axe.c
--- src/sys/dev/usb/if_axe.c    25 Jan 2011 20:03:35 -0000      1.105
+++ src/sys/dev/usb/if_axe.c    21 Mar 2011 19:00:17 -0000
@@ -1018,7 +1018,8 @@ axe_rxeof(usbd_xfer_handle xfer, usbd_pr
 
        do {
                if (sc->axe_flags & AX178 || sc->axe_flags & AX772) {
-                       if (total_len < sizeof(hdr)) {
+                       if (total_len < sizeof(hdr) ||
+                           total_len > sc->axe_bufsz) {
                                ifp->if_ierrors++;
                                goto done;
                        }
@@ -1048,8 +1049,15 @@ axe_rxeof(usbd_xfer_handle xfer, usbd_pr
                        else
                                total_len -= pktlen;
                } else {
+                       if (total_len < sizeof(hdr) ||
+                           total_len > sc->axe_bufsz) {
+                           ifp->if_ierrors++;
+                           goto done;
+                       }
+                       else {
                        pktlen = total_len; /* crc on the end? */
                        total_len = 0;
+                       }
                }
 
                m = axe_newbuf();
Index: src/sys/dev/usb/if_aue.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/if_aue.c,v
retrieving revision 1.84
diff -u -p -r1.84 if_aue.c
--- src/sys/dev/usb/if_aue.c    25 Jan 2011 20:03:35 -0000      1.84
+++ src/sys/dev/usb/if_aue.c    21 Mar 2011 19:00:23 -0000
@@ -1078,12 +1078,13 @@ aue_rxeof(usbd_xfer_handle xfer, usbd_pr
 
        usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
 
-       memcpy(mtod(c->aue_mbuf, char *), c->aue_buf, total_len);
-
-       if (total_len <= 4 + ETHER_CRC_LEN) {
+       /* frame may still be valid but length is bogus */
+       if (total_len <= 4 + ETHER_CRC_LEN || total_len > AUE_BUFSZ) {
                ifp->if_ierrors++;
                goto done;
        }
+       
+       memcpy(mtod(c->aue_mbuf, char *), c->aue_buf, total_len);
 
        memcpy(&r, c->aue_buf + total_len - 4, sizeof(r));
 
Index: src/sys/dev/usb/if_cdce.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/if_cdce.c,v
retrieving revision 1.49
diff -u -p -r1.49 if_cdce.c
--- src/sys/dev/usb/if_cdce.c   25 Jan 2011 20:03:35 -0000      1.49
+++ src/sys/dev/usb/if_cdce.c   21 Mar 2011 19:00:25 -0000
@@ -776,8 +776,11 @@ cdce_rxeof(usbd_xfer_handle xfer, usbd_p
        usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
        if (sc->cdce_flags & CDCE_ZAURUS)
                total_len -= 4; /* Strip off CRC added by Zaurus */
-       if (total_len <= 1)
+
+       if (total_len <= 1 || total_len > CDCE_BUFSZ) {
+               ifp->if_ierrors++;
                goto done;
+       }
 
        m = c->cdce_mbuf;
        memcpy(mtod(m, char *), c->cdce_buf, total_len);
Index: src/sys/dev/usb/if_cue.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/if_cue.c,v
retrieving revision 1.59
diff -u -p -r1.59 if_cue.c
--- src/sys/dev/usb/if_cue.c    25 Jan 2011 20:03:35 -0000      1.59
+++ src/sys/dev/usb/if_cue.c    21 Mar 2011 19:00:29 -0000
@@ -738,6 +738,11 @@ cue_rxeof(usbd_xfer_handle xfer, usbd_pr
 
        usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
 
+       if (total_len < sizeof(struct ether_header) ||total_len > CUE_BUFSZ) {
+               ifp->if_ierrors++;
+               goto done;
+       }
+
        memcpy(mtod(c->cue_mbuf, char *), c->cue_buf, total_len);
 
        m = c->cue_mbuf;
Index: src/sys/dev/usb/if_kue.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/if_kue.c,v
retrieving revision 1.63
diff -u -p -r1.63 if_kue.c
--- src/sys/dev/usb/if_kue.c    25 Jan 2011 20:03:35 -0000      1.63
+++ src/sys/dev/usb/if_kue.c    21 Mar 2011 19:00:34 -0000
@@ -741,8 +741,10 @@ kue_rxeof(usbd_xfer_handle xfer, usbd_pr
                     __func__, total_len,
                     UGETW(mtod(c->kue_mbuf, u_int8_t *))));
 
-       if (total_len <= 1)
+       if (total_len <= 1 || total_len > KUE_BUFSZ) {
+               ifp->if_ierrors++;
                goto done;
+       }
 
        m = c->kue_mbuf;
        /* copy data to mbuf */
Index: src/sys/dev/usb/if_mos.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/if_mos.c,v
retrieving revision 1.14
diff -u -p -r1.14 if_mos.c
--- src/sys/dev/usb/if_mos.c    21 Feb 2011 19:48:41 -0000      1.14
+++ src/sys/dev/usb/if_mos.c    21 Mar 2011 19:00:38 -0000
@@ -954,9 +954,12 @@ mos_rxeof(usbd_xfer_handle xfer, usbd_pr
        }
 
        usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
-
-       if (total_len <= 1)
+       
+       /* rxstat may still be valid, but the length is bogus */
+       if (total_len <= 1 || total_len > MOS_BUFSZ) {
+               ifp->if_ierrors++;
                goto done;
+       }
 
        /* evaluate status byte at the end */
        pktlen = total_len - 1;
Index: src/sys/dev/usb/if_url.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/if_url.c,v
retrieving revision 1.61
diff -u -p -r1.61 if_url.c
--- src/sys/dev/usb/if_url.c    25 Jan 2011 20:03:35 -0000      1.61
+++ src/sys/dev/usb/if_url.c    21 Mar 2011 19:00:40 -0000
@@ -995,12 +995,13 @@ url_rxeof(usbd_xfer_handle xfer, usbd_pr
 
        usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
 
-       memcpy(mtod(c->url_mbuf, char *), c->url_buf, total_len);
-
-       if (total_len <= ETHER_CRC_LEN) {
+       /* RX status may be valid, but the length is bogus */
+       if (total_len <= ETHER_CRC_LEN || total_len > URL_BUFSZ) {
                ifp->if_ierrors++;
                goto done;
        }
+
+       memcpy(mtod(c->url_mbuf, char *), c->url_buf, total_len);
 
        memcpy(&rxhdr, c->url_buf + total_len - ETHER_CRC_LEN, sizeof(rxhdr));

Reply via email to