COMMAND

    fragmentation

SYSTEMS AFFECTED

    FreeBSD 3.0, FreeBSD-current before the correction date.

PROBLEM

    Following is based on  FreeBSD Security Advisory.   IP connections
    are controlled through  a series of  packets that are  received by
    the two computers  involved in the  connection.  When  packets are
    too large  to be  sent in  a single  IP packet  (due to  interface
    hardware limitations for example), they can be fragmented  (unless
    prohibited by  the Don't  Fragment flag).   The final  destination
    will reassemble all the fragments of  an IP packet and pass it  to
    higher protocol layers (like TCP or UDP).

    There is a bug in the IP fragment reassembly code that might  lead
    to a  kernel panic.  An attacker  can create  and send  a pair  of
    malformed IP packets  which are then  reassembled into an  invalid
    UDP datagram. Such  an UDP datagram  would then cause  a server to
    panic and crash.  When this bug is exploited the operating  system
    will  panic.   This  results  in  a  reboot  of  the system.  This
    vulnerability has  been discussed  in public  security forums  and
    exploit programs are circulating to take advantage of this bug.

SOLUTION

    This  was  cerrected  in  FreeBSD-3.0  and  FreeBSD-current  as of
    1998/10/27  Patches are available at:

        ftp://ftp.freebsd.org/pub/FreeBSD/CERT/patches/SA-98:08/

    Patch:

        Index: ip_input.c
        ===================================================================
        RCS file: /home/cvsup/freebsd/CVS/src/sys/netinet/ip_input.c,v
        retrieving revision 1.102
        retrieving revision 1.103
        diff -u -u -r1.102 -r1.103
        --- ip_input.c      1998/10/16 03:55:01     1.102
        +++ ip_input.c      1998/10/27 09:11:41     1.103
        @@ -750,7 +750,7 @@
             * if they are completely covered, dequeue them.
             */
            for (; q != NULL && ip->ip_off + ip->ip_len > GETIP(q)->ip_off;
        -        p = q, q = nq) {
        +        q = nq) {
                    i = (ip->ip_off + ip->ip_len) -
                        GETIP(q)->ip_off;
                    if (i < GETIP(q)->ip_len) {