Linux autofs overflow in 2.0.36+

From: Brian Jones (balifat_private)
Date: Thu Feb 18 1999 - 21:09:29 PST

  • Next message: David LeBlanc: "Re: ISS Internet Scanner Brute Force Bug"

    -----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 <balifat_private>
    Contributors: Patrick Lewis <patrickat_private>,
                  phazer <phazerat_private>
    _____________________________________________________________________________
    
                                      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 balifat_private 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-----
    
    ---
    Balifat_private - http://setiathome.ssl.berkeley.edu/ - Get ready in April
                              N = N* fp ne fl fi fc fL
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 14:35:59 PDT