Re: [PATCH] Fix for kernel crash with udav(4) device
On Sun, Mar 20, 2011 at 04:07:33PM -0400, Loganaden Velvindron wrote: With input from mk, we improved the diff. Testing is very much appreciated. [...] I can't comment on the code (it isn't my area, but, worse, i'm still too short of time), but at least a make build over nfs now finished without any problems. Ciao, Kili 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 - 1.54 +++ src/sys/dev/usb/if_udav.c 20 Mar 2011 19:58:51 - @@ -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 - 1.11 +++ src/sys/dev/usb/if_udavreg.h 20 Mar 2011 19:58:51 - @@ -200,6 +200,6 @@ struct udav_rx_hdr { #define UDAV_RX_HDRLEN sizeof(struct udav_rx_hdr) /* Packet length */ -#define UDAV_MAX_MTU1536 /* XXX: max frame size is unknown */ +#define UDAV_MAX_MTU1522 /* According to datasheet */ #define UDAV_MIN_FRAME_LEN 60 #define UDAV_BUFSZ UDAV_MAX_MTU + UDAV_RX_HDRLEN -- Password: You speak an infinite deal of nothing -- sudo(8), OpenBSD
Re: [PATCH] Fix for kernel crash with udav(4) device
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 - 1.54 +++ src/sys/dev/usb/if_udav.c 20 Mar 2011 19:58:51 - @@ -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.h6 Dec 2010 04:41:39 - 1.11 +++ src/sys/dev/usb/if_udavreg.h20 Mar 2011 19:58:51 - @@ -200,6 +200,6 @@ struct udav_rx_hdr { #define UDAV_RX_HDRLEN sizeof(struct udav_rx_hdr) /* Packet length */ -#defineUDAV_MAX_MTU1536 /* XXX: max frame size is unknown */ +#defineUDAV_MAX_MTU1522 /* According to datasheet */ #defineUDAV_MIN_FRAME_LEN 60 #defineUDAV_BUFSZ UDAV_MAX_MTU + UDAV_RX_HDRLEN
Re: [PATCH] Fix for kernel crash with udav(4) device
Ok, I tested it with an NFS server, and also tested it with SFTP. The original diff works fine with the original diff. udav(4) uses 1514 bytes for largest values of total_len. //Logan C-x-C-c
[PATCH] Fix for kernel crash with udav(4) device
This device: udav0 at uhub5 port 2 ShanTou DM9601 rev 1.10/1.01 addr 2 udav0: address 00:60:6e:00:6e:20 amphy0 at udav0 phy 0: DM9601 10/100 PHY, rev. 0 causes a kernel crash with the following messages: memcpy() at memcpy+0x16 usb_transfer_complete() at usb_transfer_complete+0x256 uhci_softintr() at uchi_softintr+0x40 softintr_dispatch() at softintr_dispatch+0x5d end trace frame:0x0,count:-5 Using printf() with total_len shows that at certain times, it is 54768, where it should be less than the maximum frame size. Experimentally, the maximum value of total_len is 1514, but in if_udavreg.h, it is 1536. Index: src/sys/dev/usb/if_udav.c === RCS file: /cvs/src/sys/dev/usb/if_udav.c,v retrieving revision 1.51 diff -u -p -r1.51 if_udav.c --- src/sys/dev/usb/if_udav.c 25 Jan 2011 20:03:35 - 1.51 +++ src/sys/dev/usb/if_udav.c 14 Mar 2011 12:17:40 - @@ -1139,6 +1139,7 @@ udav_rxeof(usbd_xfer_handle xfer, usbd_p } if (total_len sizeof(struct ether_header) || + total_len UDAV_MAX_MTU || h-pktstat UDAV_RSR_ERR) { ifp-if_ierrors++; goto done;