Re: Insufficient allocations in net/unix/garbage.c

From: Aleph One (aleph1at_private)
Date: Thu Dec 04 1997 - 11:06:01 PST

  • Next message: Alan Cox: "Re: Fw: Insufficient allocations in net/unix/garbage.c (fwd)"

    ---------- Forwarded message ----------
    Date: Thu, 4 Dec 1997 02:18:29 -0500 (EST)
    From: Floody <floodat_private>
    Reply-To: linux-securityat_private
    To: Alan Cox <alanat_private>
    Cc: linux-alertat_private, linux-securityat_private
    Subject: [linux-security] Re: [linux-alert] Re: Insufficient allocations in net/unix/garbage.c
    
    On Wed, 3 Dec 1997, Alan Cox wrote:
    
    > > 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
    >
    > Yep. I know about this. The as shipped systems are all fine, if you up
    > it you need to change it. 2.1.x fixed this a while ago
    >
    > > !   stack=(unix_socket **)kmalloc(max_stack * sizeof(unix_socket **),
    > > !                                       GFP_KERNEL);
    >
    > This is not good. With a very large set of fd's you can now have the kmalloc
    > hang forever deadlocking the fd recovery. Use vmalloc and your idea is
    > correct.
    >
    > (see 2.1.x)
    
    I see.  For everyone else's benefit, here is an amended patch that
    correctly uses vmalloc() instead of kmalloc() in order to avoid the
    possible deadlocks that Alan mentioned.  Again, this is only necessary for
    2.0.x kernels, when the maximum number of open files has been increased
    beyond 1024 (which is becoming increasingly common for heavily loaded
    production servers).
    
    *** net/unix/garbage.c.orig     Wed Dec  3 14:55:10 1997
    --- net/unix/garbage.c  Thu Dec  4 02:05:47 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 vmalloc() 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,173 ----
            if(in_unix_gc)
                    return;
            in_unix_gc=1;
    !
    !       max_stack = max_files;
    !
    !       stack=(unix_socket **)vmalloc(max_stack * sizeof(unix_socket **));
    !       if (!stack) {
    !               in_unix_gc=0;
    !               return;
    !       }
    
            /*
             *      Assume everything is now unmarked
    ***************
    *** 276,280 ****
    
            in_unix_gc=0;
    
    !       free_page((long)stack);
      }
    --- 291,295 ----
    
            in_unix_gc=0;
    
    !       vfree(stack);
      }
    
    --
    ----------------------------------------------------------------------
    Please refere to the information about this list as well as general
    information about Linux security at http://www.aoy.com/Linux/Security.
    ----------------------------------------------------------------------
    
    To unsubscribe: mail -s unsubscribe test-list-requestat_private < /dev/null
    



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