---

FreeBSD Security Advisory: FreeBSD-SA-00:23.ip-options

Date: Thu, 22 Jun 2000 14:50:52 -0700
From: FreeBSD Security Advisories
security-advisories@freebsd.org
To: BUGTRAQ@SECURITYFOCUS.COM
Subject: FreeBSD Security Advisory: FreeBSD-SA-00:23.ip-options


FreeBSD-SA-00:23                                           Security Advisory
                                                                FreeBSD, Inc.

Topic:          Remote denial-of-service in IP stack

Category:       core
Module:         kernel
Announced:      2000-06-19
Affects:        FreeBSD systems prior to the correction date
Credits:        NetBSD Security Advisory 2000-002, and
                Jun-ichiro itojun Hagino 
Corrected:      (Several bugs fixed, the date below is that of the most
                recent fix)
                2000-06-08 (3.4-STABLE)
                2000-06-08 (4.0-STABLE)
                2000-06-02 (5.0-CURRENT)
FreeBSD only:   NO

I. Background

II. Problem Description

There are several bugs in the processing of IP options in the
FreeBSD IP stack, which fail to correctly bounds-check arguments
and contain other coding errors leading to the possibility of data
corruption and a kernel panic upon reception of certain invalid IP
packets.

This set of bugs includes the instance of the vulnerability
described in NetBSD Security Advisory 2000-002 (see
ftp://ftp.NetBSD.ORG/pub/NetBSD/misc/security/advisories/NetBSD-SA2000-002.txt.asc
)
as well as other bugs with similar effect.

III. Impact

Remote users can cause a FreeBSD system to panic and reboot.

IV. Workaround

None available.

V. Solution

One of the following:

1) Upgrade your FreeBSD system to 3.4-STABLE, 4.0-STABLE or
5.0-CURRENT after the respective correction dates.

2) Apply the patch below and recompile your kernel.

Either save this advisory to a file, or download the patch and
detached PGP signature from the following locations, and verify the
signature using your PGP utility.


ftp://ftp.freebsd.org/pub/FreeBSD/CERT/patches/SA-00:23/ip_options.diff


ftp://ftp.freebsd.org/pub/FreeBSD/CERT/patches/SA-00:23/ip_options.diff.asc

# cd /usr/src/sys/netinet
# patch -p < /path/to/patch_or_advisory

[ Recompile your kernel as described in http://www.freebsd.org/handbook/kernelconfig.html
and reboot the system ]

    Index: ip_icmp.c
    ===================================================================
    RCS file: /ncvs/src/sys/netinet/ip_icmp.c,v
    retrieving revision 1.39
    diff -u -r1.39 ip_icmp.c
    --- ip_icmp.c       2000/01/28 06:13:09     1.39
    +++ ip_icmp.c       2000/06/08 15:26:39
    @@ -662,8 +662,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;
                            }
                            /*
    Index: ip_input.c
    ===================================================================
    RCS file: /ncvs/src/sys/netinet/ip_input.c,v
    retrieving revision 1.130
    diff -u -r1.130 ip_input.c
    --- ip_input.c      2000/02/23 20:11:57     1.130
    +++ ip_input.c      2000/06/08 15:25:46
    @@ -1067,8 +1067,12 @@
                if (opt == IPOPT_NOP)
                        optlen = 1;
                else {
    +                   if (cnt < IPOPT_OLEN + sizeof(*cp)) {
    +                           code = &cp[IPOPT_OLEN] - (u_char *)ip;
    +                           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;
                        }
    @@ -1174,6 +1178,10 @@
                        break;

                case IPOPT_RR:
    +                   if (optlen < IPOPT_OFFSET + sizeof(*cp)) {
    +                           code = &cp[IPOPT_OFFSET] - (u_char *)ip;
    +                           goto bad;
    +                   }
                        if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
                                code = &cp[IPOPT_OFFSET] - (u_char *)ip;
                                goto bad;
    Index: ip_output.c
    ===================================================================
    RCS file: /ncvs/src/sys/netinet/ip_output.c,v
    retrieving revision 1.99
    diff -u -r1.99 ip_output.c
    --- ip_output.c     2000/03/09 14:57:15     1.99
    +++ ip_output.c     2000/06/08 15:27:08
    @@ -1302,8 +1302,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) {

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends, & analysis