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,
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to