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));