Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 16 May 2019 11:09:53 +0000 (UTC)
From:      Michael Tuexen <tuexen@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r347685 - stable/11/sys/netinet
Message-ID:  <201905161109.x4GB9rxb098674@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: tuexen
Date: Thu May 16 11:09:53 2019
New Revision: 347685
URL: https://svnweb.freebsd.org/changeset/base/347685

Log:
  MFC r346182:
  
  When sending IPv4 packets on a SOCK_RAW socket using the IP_HDRINCL option,
  ensure that the ip_hl field is valid. Furthermore, ensure that the complete
  IPv4 header is contained in the first mbuf. Finally, move the length checks
  before relying on them when accessing fields of the IPv4 header.

Modified:
  stable/11/sys/netinet/raw_ip.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/netinet/raw_ip.c
==============================================================================
--- stable/11/sys/netinet/raw_ip.c	Thu May 16 10:43:52 2019	(r347684)
+++ stable/11/sys/netinet/raw_ip.c	Thu May 16 11:09:53 2019	(r347685)
@@ -439,7 +439,7 @@ rip_output(struct mbuf *m, struct socket *so, ...)
 	u_long dst;
 	int flags = ((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0) |
 	    IP_ALLOWBROADCAST;
-	int cnt;
+	int cnt, hlen;
 	u_char opttype, optlen, *cp;
 
 	va_start(ap, so);
@@ -495,33 +495,40 @@ rip_output(struct mbuf *m, struct socket *so, ...)
 			m_freem(m);
 			return(EMSGSIZE);
 		}
-		INP_RLOCK(inp);
 		ip = mtod(m, struct ip *);
-		error = prison_check_ip4(inp->inp_cred, &ip->ip_src);
-		if (error != 0) {
-			INP_RUNLOCK(inp);
-			m_freem(m);
-			return (error);
+		hlen = ip->ip_hl << 2;
+		if (m->m_len < hlen) {
+			m = m_pullup(m, hlen);
+			if (m == NULL)
+				return (EINVAL);
+			ip = mtod(m, struct ip *);
 		}
 
+		INP_RLOCK(inp);
 		/*
 		 * Don't allow both user specified and setsockopt options,
 		 * and don't allow packet length sizes that will crash.
 		 */
-		if (((ip->ip_hl != (sizeof (*ip) >> 2)) && inp->inp_options)
-		    || (ntohs(ip->ip_len) != m->m_pkthdr.len)
-		    || (ntohs(ip->ip_len) < (ip->ip_hl << 2))) {
+		if ((hlen < sizeof (*ip))
+		    || ((hlen > sizeof (*ip)) && inp->inp_options)
+		    || (ntohs(ip->ip_len) != m->m_pkthdr.len)) {
 			INP_RUNLOCK(inp);
 			m_freem(m);
 			return (EINVAL);
 		}
+		error = prison_check_ip4(inp->inp_cred, &ip->ip_src);
+		if (error != 0) {
+			INP_RUNLOCK(inp);
+			m_freem(m);
+			return (error);
+		}
 		/*
 		 * Don't allow IP options which do not have the required
 		 * structure as specified in section 3.1 of RFC 791 on
 		 * pages 15-23.
 		 */
 		cp = (u_char *)(ip + 1);
-		cnt = (ip->ip_hl << 2) - sizeof (struct ip);
+		cnt = hlen - sizeof (struct ip);
 		for (; cnt > 0; cnt -= optlen, cp += optlen) {
 			opttype = cp[IPOPT_OPTVAL];
 			if (opttype == IPOPT_EOL)



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