Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: Simplify the IPv4 parser. Get the option length in ...



details:   https://anonhg.NetBSD.org/src/rev/f92b9003e6e3
branches:  trunk
changeset: 318360:f92b9003e6e3
user:      maxv <maxv%NetBSD.org@localhost>
date:      Wed Apr 18 17:58:07 2018 +0000
description:
Simplify the IPv4 parser. Get the option length in 'optlen', and sanitize
it earlier. A new check is added (off + optlen > skip).

In the IPv6 parser we reuse 'optlen', and remove 'ad' as a result.

diffstat:

 sys/netipsec/xform_ah.c |  85 ++++++++++++++----------------------------------
 1 files changed, 25 insertions(+), 60 deletions(-)

diffs (165 lines):

diff -r d871158c874b -r f92b9003e6e3 sys/netipsec/xform_ah.c
--- a/sys/netipsec/xform_ah.c   Wed Apr 18 17:34:54 2018 +0000
+++ b/sys/netipsec/xform_ah.c   Wed Apr 18 17:58:07 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: xform_ah.c,v 1.89 2018/04/16 17:32:34 maxv Exp $       */
+/*     $NetBSD: xform_ah.c,v 1.90 2018/04/18 17:58:07 maxv Exp $       */
 /*     $FreeBSD: src/sys/netipsec/xform_ah.c,v 1.1.4.1 2003/01/24 05:11:36 sam Exp $   */
 /*     $OpenBSD: ip_ah.c,v 1.63 2001/06/26 06:18:58 angelos Exp $ */
 /*
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xform_ah.c,v 1.89 2018/04/16 17:32:34 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xform_ah.c,v 1.90 2018/04/18 17:58:07 maxv Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_inet.h"
@@ -266,7 +266,7 @@
 {
        struct mbuf *m = *m0;
        unsigned char *ptr;
-       int off, count;
+       int off, count, optlen;
 #ifdef INET
        struct ip *ip;
 #endif
@@ -274,7 +274,7 @@
        struct ip6_ext *ip6e;
        struct ip6_hdr ip6;
        struct ip6_rthdr *rh;
-       int alloc, ad, nxt;
+       int alloc, nxt;
 #endif
 
        switch (proto) {
@@ -308,56 +308,32 @@
 
                /* IPv4 option processing */
                for (off = sizeof(struct ip); off < skip;) {
-                       if (ptr[off] == IPOPT_EOL || ptr[off] == IPOPT_NOP ||
-                           off + 1 < skip)
-                               ;
-                       else {
-                               DPRINTF(("%s: illegal IPv4 option length for "
-                                   "option %d\n", __func__, ptr[off]));
-
+                       if (ptr[off] == IPOPT_EOL) {
+                               break;
+                       } else if (ptr[off] == IPOPT_NOP) {
+                               optlen = 1;
+                       } else if (off + 1 < skip) {
+                               optlen = ptr[off + 1];
+                               if (optlen < 2 || off + optlen > skip) {
+                                       m_freem(m);
+                                       return EINVAL;
+                               }
+                       } else {
                                m_freem(m);
                                return EINVAL;
                        }
 
                        switch (ptr[off]) {
-                       case IPOPT_EOL:
-                               off = skip;  /* End the loop. */
-                               break;
-
                        case IPOPT_NOP:
-                               off++;
-                               break;
-
-                       case IPOPT_SECURITY:    /* 0x82 */
+                       case IPOPT_SECURITY:
                        case 0x85:      /* Extended security. */
                        case 0x86:      /* Commercial security. */
                        case 0x94:      /* Router alert */
                        case 0x95:      /* RFC1770 */
-                               /* Sanity check for option length. */
-                               if (ptr[off + 1] < 2) {
-                                       DPRINTF(("%s: illegal IPv4 option "
-                                           "length for option %d\n", __func__,
-                                           ptr[off]));
-
-                                       m_freem(m);
-                                       return EINVAL;
-                               }
-
-                               off += ptr[off + 1];
                                break;
 
                        case IPOPT_LSRR:
                        case IPOPT_SSRR:
-                               /* Sanity check for option length. */
-                               if (ptr[off + 1] < 2) {
-                                       DPRINTF(("%s: illegal IPv4 option "
-                                           "length for option %d\n", __func__,
-                                           ptr[off]));
-
-                                       m_freem(m);
-                                       return EINVAL;
-                               }
-
                                /*
                                 * On output, if we have either of the
                                 * source routing options, we should
@@ -369,32 +345,21 @@
                                 */
                                if (out)
                                        memcpy(&ip->ip_dst,
-                                           ptr + off + ptr[off + 1] -
+                                           ptr + off + optlen -
                                            sizeof(struct in_addr),
                                            sizeof(struct in_addr));
+                               /* FALLTHROUGH */
 
-                               /* Fall through */
                        default:
-                               /* Sanity check for option length. */
-                               if (ptr[off + 1] < 2) {
-                                       DPRINTF(("%s: illegal IPv4 option "
-                                           "length for option %d\n", __func__,
-                                           ptr[off]));
-                                       m_freem(m);
-                                       return EINVAL;
-                               }
-
                                /* Zeroize all other options. */
-                               count = ptr[off + 1];
-                               memcpy(ptr + off, ipseczeroes, count);
-                               off += count;
+                               memcpy(ptr + off, ipseczeroes, optlen);
                                break;
                        }
 
+                       off += optlen;
+
                        /* Sanity check. */
                        if (off > skip) {
-                               DPRINTF(("%s: malformed IPv4 options header\n",
-                                       __func__));
                                m_freem(m);
                                return EINVAL;
                        }
@@ -487,17 +452,17 @@
                                        if (count + 1 >= noff) {
                                                goto error6;
                                        }
-                                       ad = ptr[count + 1] + 2;
+                                       optlen = ptr[count + 1] + 2;
 
-                                       if (count + ad > noff) {
+                                       if (count + optlen > noff) {
                                                goto error6;
                                        }
 
                                        if (ptr[count] & IP6OPT_MUTABLE) {
-                                               memset(ptr + count, 0, ad);
+                                               memset(ptr + count, 0, optlen);
                                        }
 
-                                       count += ad;
+                                       count += optlen;
                                }
 
                                if (count != noff) {



Home | Main Index | Thread Index | Old Index