Author: tuexen
Date: Thu May 16 08:50:25 2019
New Revision: 347660
URL: https://svnweb.freebsd.org/changeset/base/347660

Log:
  MFC r344048:
  
  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.

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 08:47:28 2019        
(r347659)
+++ stable/11/sys/netinet/raw_ip.c      Thu May 16 08:50:25 2019        
(r347660)
@@ -439,6 +439,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);
@@ -512,6 +514,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-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to