Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 27 Jun 2014 10:24:36 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r267955 - head/sys/dev/usb/net
Message-ID:  <201406271024.s5RAOaCe096697@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Fri Jun 27 10:24:36 2014
New Revision: 267955
URL: http://svnweb.freebsd.org/changeset/base/267955

Log:
  Add proper rangechecks in "axge_rx_frame()" function and
  fix receive loop header parsing.
  
  MFC after:	3 days
  PR:		191432

Modified:
  head/sys/dev/usb/net/if_axge.c

Modified: head/sys/dev/usb/net/if_axge.c
==============================================================================
--- head/sys/dev/usb/net/if_axge.c	Fri Jun 27 10:07:00 2014	(r267954)
+++ head/sys/dev/usb/net/if_axge.c	Fri Jun 27 10:24:36 2014	(r267955)
@@ -929,14 +929,19 @@ axge_ioctl(struct ifnet *ifp, u_long cmd
 static int
 axge_rx_frame(struct usb_ether *ue, struct usb_page_cache *pc, int actlen)
 {
-	int error, pos;
+	int error;
+	int pos;
 	int pkt_cnt;
-	uint32_t rxhdr, pkt_hdr;
-	uint16_t hdr_off;
-	uint16_t len, pktlen; 
+	uint32_t rxhdr;
+	uint32_t pkt_hdr;
+	uint32_t hdr_off;
+	uint32_t pktlen; 
+
+	/* verify we have enough data */
+	if (actlen < (int)sizeof(rxhdr))
+		return (EINVAL);
 
 	pos = 0;
-	len = 0;
 	error = 0;
 
 	usbd_copy_out(pc, actlen - sizeof(rxhdr), &rxhdr, sizeof(rxhdr));
@@ -945,25 +950,29 @@ axge_rx_frame(struct usb_ether *ue, stru
 	pkt_cnt = (uint16_t)rxhdr;
 	hdr_off = (uint16_t)(rxhdr >> 16);
 
-	usbd_copy_out(pc, hdr_off, &pkt_hdr, sizeof(pkt_hdr));
-
 	while (pkt_cnt > 0) {
-		if ((int)(sizeof(pkt_hdr)) > actlen) {
+		/* verify the header offset */
+		if ((int)(hdr_off + sizeof(pkt_hdr)) > actlen) {
 			error = EINVAL;
 			break;
 		}
+		usbd_copy_out(pc, hdr_off, &pkt_hdr, sizeof(pkt_hdr));
+
 		pkt_hdr = le32toh(pkt_hdr);
 		pktlen = (pkt_hdr >> 16) & 0x1fff;
 		if ((pkt_hdr & AXGE_RXHDR_CRC_ERR) ||
 		    (pkt_hdr & AXGE_RXHDR_DROP_ERR))
 			ue->ue_ifp->if_ierrors++;
+		/* verify the data payload */
+		if (pktlen < 6 || (int)(pos + 2 + pktlen - 6) > actlen) {
+			error = EINVAL;
+			break;
+		}
 		axge_rxeof(ue, pc, pos + 2, pktlen - 6, pkt_hdr);
-		len = (pktlen + 7) & ~7;
-		pos += len;
-		pkt_hdr++;
+		pos += (pktlen + 7) & ~7;
+		hdr_off += sizeof(pkt_hdr);
 		pkt_cnt--;
 	}
-
 	if (error != 0)
 		ue->ue_ifp->if_ierrors++;
 	return (error);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201406271024.s5RAOaCe096697>