The OpenNET Project
 
Search (keywords):  SOFT ARTICLES TIPS & TRICKS SECURITY
LINKS NEWS MAN DOCUMENTATION


Insufficient allocations in net/unix/garbage.c


<< Previous INDEX Search src Set bookmark Go to bookmark Next >>
X-RDate: Sun, 13 Jan 1980 10:01:02 +0500 (SSK)
Date: Thu, 4 Dec 1997 13:06:01 -0600
From: Aleph One <[email protected]>
To: [email protected]
Subject: Re: Insufficient allocations in net/unix/garbage.c

---------- Forwarded message ----------
Date: Thu, 4 Dec 1997 02:18:29 -0500 (EST)
From: Floody <[email protected]>
Reply-To: [email protected]
To: Alan Cox <[email protected]>
Cc: [email protected], [email protected]
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 [email protected] < /dev/null

<< Previous INDEX Search src Set bookmark Go to bookmark Next >>



Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру