COMMAND

    autofs

SYSTEMS AFFECTED

    Linux 2.0.36...2.2.1

PROBLEM

    Brian Jones found  following.  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.

    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.
    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 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.  Example:

	[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#

    Very large numbers will cause  various kernel errors, or a  reboot
    as giant chunks of memory are being clobbered.

SOLUTION

    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.
    Author  was  contacted  and  said  he  was  going  to  fix this at
    a different point in  the code.  This  seems to work for  the time
    being.

    --- 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;