I haven't seen this on the linux-security list so I thought I'd forward it on for your review. It was pulled from Bugtraq by one of our sys admins. Dan _______________________________________________________________________________ Dan Yocum | Phone: (630) 840-8525 Computing Division OSS/FSS | Fax: (630) 840-6345 .~. L Fermi National Accelerator Lab | email: yocum@fnal.gov /V\ I P.O. Box 500 | WWW: www-oss.fnal.gov/~yocum/ // \\ N Batavia, IL 60510 | "TANSTAAFL" /( )\ U ________________________________|____________________________________ ^`~'^__X_ - --- Forwarded mail from Brian Jones <balif@SHELL.NACS.NET> Date: Fri, 19 Feb 1999 00:09:29 -0500 From: Brian Jones <balif@SHELL.NACS.NET> Subject: Linux autofs overflow in 2.0.36+ To: BUGTRAQ@NETSPACE.ORG Reply-to: Brian Jones <balif@SHELL.NACS.NET> - -----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 <balif@nacs.net> Contributors: Patrick Lewis <patrick@apk.net>, phazer <phazer@battlemech.nws.net> _____________________________________________________________________________ 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 balif@nacs.net 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----- - --- Balif@Nacs.Net - http://setiathome.ssl.berkeley.edu/ - Get ready in April N = N* fp ne fl fi fc fL - ---End of forwarded mail from Brian Jones <balif@SHELL.NACS.NET> ------- End of Forwarded Message