Lucene search

K
packetstormPacket StormPACKETSTORM:12200
HistoryAug 17, 1999 - 12:00 a.m.

autofs.linux.txt

1999-08-1700:00:00
Packet Storm
packetstormsecurity.com
17
`Date: Fri, 19 Feb 1999 00:09:29 -0500  
From: Brian Jones <[email protected]>  
To: [email protected]  
Subject: Linux autofs overflow in 2.0.36+  
  
-----BEGIN PGP SIGNED MESSAGE-----  
  
Overflow in Autofs - Feb 18 1999  
_____________________________________________________________________________  
Affected: Linux autofs kernel module in linux-2.0.36 to 2.2.1  
Type of Problem: Buffer overflow in kernel module.  
Effects: Denial of Service, potential root exploit  
  
By: Brian Jones <[email protected]>  
Contributors: Patrick Lewis <[email protected]>,  
phazer <[email protected]>  
_____________________________________________________________________________  
  
Summary  
  
  
The autofs kernel module does not check the size of the directory names  
it receives. It is passed the name and the names length through  
dentry->d_name.name and dentry->d_name.len respectively. Later on it  
memcpy()'s the name into a 256 byte buffer, using dentry->d_name.len as the  
number of bytes to copy, without checking its size. A nonprivilaged user may  
attempt to cd to a directory name exceeding 255 characters. This overwrites  
memory, probably the kernel stack and anything beyond it, and causes kernel  
errors or makes the machine reboot.  
  
  
Overview of Automount  
  
  
drwxr-xr-x 3 root root 0 Feb 18 17:40 misc  
  
The autofs module provides support for the automount filesystem, as  
well as the interface between the kernel and the automountd daemon, which is  
responsible for the actual mounting. Calls such as chdir() executed in the  
automount directory are handled by the module, and if the desired directory  
is defined in the configuration files, automountd then mounts that  
directory/device.  
  
  
Details  
  
  
When a chdir() or similar function is called in the autofs directory,  
by a user doing something along the lines of "cd xxxx", the function  
fs/autofs/root.c:autofs_root_lookup() is called.  
  
autofs_root_lookup() receives the name of the directory through  
"dentry->d_name.name", and it's length through "dentry->d_name.len". The  
dentry structure is passed via pointer through two functions, each performing  
various operations along the way.  
  
It eventually reaches waitq:autofs_wait(). The name, length, and other  
bits of information are copied into a 'wq' structure, which stands for  
waiting queue. "wq.name" is "char *name", a pointer to the dentry pointer  
that refers back to the filename somewhere in the kernel.  
  
autofs_wait() then passes 'wq' to autofs_notify_daemon(), which copies  
the information into a structure called 'pkt'. This is passed to  
autofs_write(), which write()'s the packet down the pipe connecting the  
module with automountd.  
  
  
The Overflow  
  
  
The problem occurs when 'wq' is copied to 'pkt'. Before this point,  
the path name was shuffled around via pointers. 'pkt' is defined as:  
  
struct autofs_packet_missing pkt;  
  
struct autofs_packet_missing {  
struct autofs_packet_hdr hdr;  
autofs_wqt_t wait_queue_token;  
int len;  
char name[NAME_MAX+1];   
};  
  
NAME_MAX is 255, making pkt.name a 256 byte buffer.  
  
pkt.name is copied using this method:  
  
pkt.len = wq->len;  
memcpy(pkt.name, wq->name, pkt.len);  
pkt.name[pkt.len] = '\0';  
  
Remember that wq->len and wq->name are directly copied from the dentry  
structure. The len and name were never checked to ensure they would fit  
inside pkt's buffer. If you attempt to cd to a directory name over 255  
characters, you will overflow this buffer.  
  
Because this is running in the kernel, a large enough value can  
overwrite as much memory as you want, over top any process you want. No  
bounds checking is done, and the code makes no check to see if  
dentry->d_name.len is under 255.  
  
  
Examples  
  
  
[balif@localhost misc]# cd `perl -e 'print "x" x 255'`  
bash: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx  
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx  
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx  
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:  
No such file or directory  
  
[balif@localhost misc]# cd `perl -e 'print "x" x 256'`  
invalid operand: 0000  
CPU: 0  
EIP: 0010:[<c0155b00>]  
EFLAGS: 00010282  
eax: 00000000 ebx: c2a90c20 ecx: c265904c edx: c0000000  
esi: c29d3b00 edi: c2928000 ebp: c260d940 esp: c26c5ee8  
ds: 0018 es: 0018 ss: 0018  
Process bash (pid: 360, process nr: 21, stackpage=c26c5000)  
Stack: 00000000 00000000 c260d940 c260d900 00000286 c0154c58 c0154ca8  
c2928000 c260d940 c2928000 c260d900 c2659d50 c26cd3a0 00000286 c0154def  
c260d900 c029c000 c2928000 c2659d9c c260d900 c2659d50 c0154ef7 c260d900  
c260d900 c029c000 c2928000 c2659d9c c260d900 c2659d50 c0154ef7 c260d900  
c260d900  
Call Trace: [<c0154c58>] [<c0154ca8>] [<c0154def>] [<c0154ef7>] [<c0128759>]  
[<c0128912>] [<c01289e9>] [<c012126e>] [<c0107a40>]  
Code: fe ff ff 83 c4 08 eb 03 ff 43 1c 8b 7c 24 1c 83 7f 0c 00 74  
- -{Shell dies}-  
  
/var/log/messages  
Feb 16 23:09:13 localhost automount[1361]: attempting to mount entry  
/misc/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx  
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx  
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx  
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxq%^D^HH#  
  
^_ buffer has been exceeded  
  
Very large numbers will cause various kernel errors, or a reboot as giant  
chunks of memory are being clobbered.  
  
  
The Fix  
  
  
This quick fix limits the length of a directory name to 255  
characters, and patches /usr/src/linux-2.2.1/fs/autofs/root.c. I contacted  
the author, who said he was going to fix this at a different point in the  
code. This seems to work for the time being.  
  
[---cut here---]  
- --- root.c.orig Thu Feb 18 20:26:23 1999  
+++ root.c Thu Feb 18 20:26:17 1999  
@@ -217,6 +217,11 @@  
DPRINTK(("autofs_root_lookup: name = "));  
autofs_say(dentry->d_name.name,dentry->d_name.len);  
  
+ /* quick patch by [email protected] 2-18-99 */  
+ /* Prevents overflow of pkt.name in waitq.c:autofs_notify_daemon() */  
+ if (dentry->d_name.len > 255)  
+ return -ENAMETOOLONG;  
+  
if (!S_ISDIR(dir->i_mode))  
return -ENOTDIR;  
[---cut here---]  
  
  
-----BEGIN PGP SIGNATURE-----  
Version: 2.6.3a  
Charset: noconv  
  
iQB1AwUBNszxXSMC9wnJPLr1AQEvOQMAgeWVliqaW0CrM0NMsybSmw/a4yKdEJ4V  
QkzVY+E9bb7wwMGxmC4nxJyhiUn9f9I4f0S19LMON0g7rBRQqlUi3rfgVOsBa18g  
wBfY1bF3iwV7zYph08Tqd7So31j/ux7S  
=88Co  
-----END PGP SIGNATURE-----  
  
---  
[email protected] - http://setiathome.ssl.berkeley.edu/ - Get ready in April  
N = N* fp ne fl fi fc fL  
  
`