Source-Changes-HG archive

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

[src/trunk]: src/sys/netinet add missing boundary checks to ip options proces...



details:   https://anonhg.NetBSD.org/src/rev/47fed380db96
branches:  trunk
changeset: 485976:47fed380db96
user:      itojun <itojun%NetBSD.org@localhost>
date:      Wed May 10 03:31:30 2000 +0000

description:
add missing boundary checks to ip options processing.
correct timestamp option validation (len and ptr upper/lower bound
based on RFC791).
fill "pointer" field for parameter problem in timestamp option processing.

diffstat:

 sys/netinet/ip_icmp.c   |   7 +++++--
 sys/netinet/ip_input.c  |  38 ++++++++++++++++++++++++++++++++------
 sys/netinet/ip_output.c |  18 ++++++++++++++----
 3 files changed, 51 insertions(+), 12 deletions(-)

diffs (161 lines):

diff -r 77752bae003c -r 47fed380db96 sys/netinet/ip_icmp.c
--- a/sys/netinet/ip_icmp.c     Wed May 10 02:16:15 2000 +0000
+++ b/sys/netinet/ip_icmp.c     Wed May 10 03:31:30 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_icmp.c,v 1.44 2000/03/30 13:24:59 augustss Exp $    */
+/*     $NetBSD: ip_icmp.c,v 1.45 2000/05/10 03:31:30 itojun Exp $      */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -693,8 +693,11 @@
                            if (opt == IPOPT_NOP)
                                    len = 1;
                            else {
+                                   if (cnt < IPOPT_OLEN + sizeof(*cp))
+                                           break;
                                    len = cp[IPOPT_OLEN];
-                                   if (len <= 0 || len > cnt)
+                                   if (len < IPOPT_OLEN + sizeof(*cp) ||
+                                       len > cnt)
                                            break;
                            }
                            /*
diff -r 77752bae003c -r 47fed380db96 sys/netinet/ip_input.c
--- a/sys/netinet/ip_input.c    Wed May 10 02:16:15 2000 +0000
+++ b/sys/netinet/ip_input.c    Wed May 10 03:31:30 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_input.c,v 1.113 2000/05/10 01:19:44 itojun Exp $    */
+/*     $NetBSD: ip_input.c,v 1.114 2000/05/10 03:31:30 itojun Exp $    */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -972,7 +972,7 @@
                                goto bad;
                        }
                        optlen = cp[IPOPT_OLEN];
-                       if (optlen <= 0 || optlen > cnt) {
+                       if (optlen < IPOPT_OLEN + sizeof(*cp) || optlen > cnt) {
                                code = &cp[IPOPT_OLEN] - (u_char *)ip;
                                goto bad;
                        }
@@ -998,6 +998,10 @@
                                code = ICMP_UNREACH_NET_PROHIB;
                                goto bad;
                        }
+                       if (optlen < IPOPT_OFFSET + sizeof(*cp)) {
+                               code = &cp[IPOPT_OLEN] - (u_char *)ip;
+                               goto bad;
+                       }
                        if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
                                code = &cp[IPOPT_OFFSET] - (u_char *)ip;
                                goto bad;
@@ -1049,6 +1053,10 @@
                        break;
 
                case IPOPT_RR:
+                       if (optlen < IPOPT_OFFSET + sizeof(*cp)) {
+                               code = &cp[IPOPT_OLEN] - (u_char *)ip;
+                               goto bad;
+                       }
                        if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
                                code = &cp[IPOPT_OFFSET] - (u_char *)ip;
                                goto bad;
@@ -1080,11 +1088,20 @@
                case IPOPT_TS:
                        code = cp - (u_char *)ip;
                        ipt = (struct ip_timestamp *)cp;
-                       if (ipt->ipt_len < 5)
+                       if (ipt->ipt_len < 4 || ipt->ipt_len > 40) {
+                               code = (u_char *)&ipt->ipt_len - (u_char *)ip;
                                goto bad;
+                       }
+                       if (ipt->ipt_ptr < 5) {
+                               code = (u_char *)&ipt->ipt_ptr - (u_char *)ip;
+                               goto bad;
+                       }
                        if (ipt->ipt_ptr > ipt->ipt_len - sizeof (int32_t)) {
-                               if (++ipt->ipt_oflw == 0)
+                               if (++ipt->ipt_oflw == 0) {
+                                       code = (u_char *)&ipt->ipt_ptr -
+                                           (u_char *)ip;
                                        goto bad;
+                               }
                                break;
                        }
                        cp0 = (cp + ipt->ipt_ptr - 1);
@@ -1095,8 +1112,11 @@
 
                        case IPOPT_TS_TSANDADDR:
                                if (ipt->ipt_ptr - 1 + sizeof(n_time) +
-                                   sizeof(struct in_addr) > ipt->ipt_len)
+                                   sizeof(struct in_addr) > ipt->ipt_len) {
+                                       code = (u_char *)&ipt->ipt_ptr -
+                                           (u_char *)ip;
                                        goto bad;
+                               }
                                ipaddr.sin_addr = dst;
                                ia = ifatoia(ifaof_ifpforaddr(sintosa(&ipaddr),
                                    m->m_pkthdr.rcvif));
@@ -1109,8 +1129,11 @@
 
                        case IPOPT_TS_PRESPEC:
                                if (ipt->ipt_ptr - 1 + sizeof(n_time) +
-                                   sizeof(struct in_addr) > ipt->ipt_len)
+                                   sizeof(struct in_addr) > ipt->ipt_len) {
+                                       code = (u_char *)&ipt->ipt_ptr -
+                                           (u_char *)ip;
                                        goto bad;
+                               }
                                bcopy(cp0, &ipaddr.sin_addr,
                                    sizeof(struct in_addr));
                                if (ifatoia(ifa_ifwithaddr(sintosa(&ipaddr)))
@@ -1120,6 +1143,9 @@
                                break;
 
                        default:
+                               /* XXX can't take &ipt->ipt_flg */
+                               code = (u_char *)&ipt->ipt_ptr -
+                                   (u_char *)ip + 1;
                                goto bad;
                        }
                        ntime = iptime();
diff -r 77752bae003c -r 47fed380db96 sys/netinet/ip_output.c
--- a/sys/netinet/ip_output.c   Wed May 10 02:16:15 2000 +0000
+++ b/sys/netinet/ip_output.c   Wed May 10 03:31:30 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_output.c,v 1.73 2000/04/13 11:48:07 is Exp $        */
+/*     $NetBSD: ip_output.c,v 1.74 2000/05/10 03:31:30 itojun Exp $    */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -817,8 +817,16 @@
                        *dp++ = IPOPT_NOP;
                        optlen = 1;
                        continue;
-               } else
-                       optlen = cp[IPOPT_OLEN];
+               }
+#ifdef DIAGNOSTIC
+               if (cnt < IPOPT_OLEN + sizeof(*cp))
+                       panic("malformed IPv4 option passed to ip_optcopy");
+#endif
+               optlen = cp[IPOPT_OLEN];
+#ifdef DIAGNOSTIC
+               if (optlen < IPOPT_OLEN + sizeof(*cp) || optlen > cnt)
+                       panic("malformed IPv4 option passed to ip_optcopy");
+#endif
                /* bogus lengths should have been caught by ip_dooptions */
                if (optlen > cnt)
                        optlen = cnt;
@@ -1134,8 +1142,10 @@
                if (opt == IPOPT_NOP)
                        optlen = 1;
                else {
+                       if (cnt < IPOPT_OLEN + sizeof(*cp))
+                               goto bad;
                        optlen = cp[IPOPT_OLEN];
-                       if (optlen <= IPOPT_OLEN || optlen > cnt)
+                       if (optlen < IPOPT_OLEN  + sizeof(*cp) || optlen > cnt)
                                goto bad;
                }
                switch (opt) {



Home | Main Index | Thread Index | Old Index