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