Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 12 Feb 2019 10:17:21 +0000 (UTC)
From:      Michael Tuexen <tuexen@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r344048 - head/sys/netinet
Message-ID:  <201902121017.x1CAHLN0031793@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: tuexen
Date: Tue Feb 12 10:17:21 2019
New Revision: 344048
URL: https://svnweb.freebsd.org/changeset/base/344048

Log:
  Improve input validation for raw IPv4 socket using the IP_HDRINCL
  option.
  
  This issue was found by running syzkaller on OpenBSD.
  Greg Steuck made me aware that the problem might also exist on FreeBSD.
  
  Reported by:		Greg Steuck
  MFC after:		1 month
  Differential Revision:	https://reviews.freebsd.org/D18834

Modified:
  head/sys/netinet/raw_ip.c

Modified: head/sys/netinet/raw_ip.c
==============================================================================
--- head/sys/netinet/raw_ip.c	Tue Feb 12 09:26:05 2019	(r344047)
+++ head/sys/netinet/raw_ip.c	Tue Feb 12 10:17:21 2019	(r344048)
@@ -454,6 +454,8 @@ 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;
+	u_char opttype, optlen, *cp;
 
 	va_start(ap, so);
 	dst = va_arg(ap, u_long);
@@ -527,6 +529,34 @@ rip_output(struct mbuf *m, struct socket *so, ...)
 			INP_RUNLOCK(inp);
 			m_freem(m);
 			return (EINVAL);
+		}
+		/*
+		 * 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);
+		for (; cnt > 0; cnt -= optlen, cp += optlen) {
+			opttype = cp[IPOPT_OPTVAL];
+			if (opttype == IPOPT_EOL)
+				break;
+			if (opttype == IPOPT_NOP) {
+				optlen = 1;
+				continue;
+			}
+			if (cnt < IPOPT_OLEN + sizeof(u_char)) {
+				INP_RUNLOCK(inp);
+				m_freem(m);
+				return (EINVAL);
+			}
+			optlen = cp[IPOPT_OLEN];
+			if (optlen < IPOPT_OLEN + sizeof(u_char) ||
+			    optlen > cnt) {
+				INP_RUNLOCK(inp);
+				m_freem(m);
+				return (EINVAL);
+			}
 		}
 		/*
 		 * This doesn't allow application to specify ID of zero,



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