With input from mk, we improved the diff. Testing is very much appreciated.
mk@ suggests checking total_len right after xfer_status to make sure the header is safe to use. There's a mistake in the DPRINTF() fo RX status, one parameter is missing. This caused another crash when debug mode is enabled. it discards packets that are more than UDAV_BUFSZ even if the status is correct (This is from mk@). The datasheet mentions that a normal packet is 1522 bytes. It works with no regression on my udav(4). Index: src/sys/dev/usb/if_udav.c =================================================================== RCS file: /cvs/src/sys/dev/usb/if_udav.c,v retrieving revision 1.54 diff -u -p -r1.54 if_udav.c --- src/sys/dev/usb/if_udav.c 20 Mar 2011 17:58:26 -0000 1.54 +++ src/sys/dev/usb/if_udav.c 20 Mar 2011 19:58:51 -0000 @@ -1128,18 +1128,25 @@ udav_rxeof(usbd_xfer_handle xfer, usbd_p usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); + if (total_len < UDAV_RX_HDRLEN) { + ifp->if_ierrors++; + goto done; + } + h = (struct udav_rx_hdr *)c->udav_buf; total_len = UGETW(h->length) - ETHER_CRC_LEN; - DPRINTF(("%s: RX Status: 0x%02x\n", h->pktstat)); + DPRINTF(("%s: RX Status: 0x%02x\n", sc->sc_dev.dv_xname, h->pktstat)); if (h->pktstat & UDAV_RSR_LCS) { ifp->if_collisions++; goto done; } + /* RX status may still be correct but total_len is bogus */ if (total_len < sizeof(struct ether_header) || - h->pktstat & UDAV_RSR_ERR) { + h->pktstat & UDAV_RSR_ERR || + total_len > UDAV_BUFSZ ) { ifp->if_ierrors++; goto done; } Index: src/sys/dev/usb/if_udavreg.h =================================================================== RCS file: /cvs/src/sys/dev/usb/if_udavreg.h,v retrieving revision 1.11 diff -u -p -r1.11 if_udavreg.h --- src/sys/dev/usb/if_udavreg.h 6 Dec 2010 04:41:39 -0000 1.11 +++ src/sys/dev/usb/if_udavreg.h 20 Mar 2011 19:58:51 -0000 @@ -200,6 +200,6 @@ struct udav_rx_hdr { #define UDAV_RX_HDRLEN sizeof(struct udav_rx_hdr) /* Packet length */ -#define UDAV_MAX_MTU 1536 /* XXX: max frame size is unknown */ +#define UDAV_MAX_MTU 1522 /* According to datasheet */ #define UDAV_MIN_FRAME_LEN 60 #define UDAV_BUFSZ UDAV_MAX_MTU + UDAV_RX_HDRLEN