[VulnWatch] Linux kernel sys_uselib local root vulnerability

From: Paul Starzetz (ihaquer_at_isec.pl)
Date: 01/07/05

  • Next message: customer service mailbox: "[VulnWatch] iDEFENSE Security Advisory [IDEF0731] Exim auth_spa_server() Buffer Overflow Vulnerability"
    Date: Fri, 7 Jan 2005 12:46:18 +0100 (CET)
    To: bugtraq@securityfocus.com, <full-disclosure@lists.netsys.com>, <vulnwatch@vulnwatch.org>

    Hash: SHA1

    Hi all,

    first of all I must comply about the handling of this vulnerability that I
    reported to vendorsec. Obviously my code posted there has been stolen and
    plagiated by Stefan Esser from Ematters. The posting containing the
    plagiate will follow. Now I have been forced to release the full advisory
    however another disclosure timeline have been agreed on vendorsec. Sorry
    for the inconvenience.

    - ---------------------------------------------------------------------------

    Synopsis: Linux kernel uselib() privilege elevation
    Product: Linux kernel
    Version: 2.4 up to and including 2.4.29-rc2, 2.6 up to and including 2.6.10
    Vendor: http://www.kernel.org/
    URL: http://isec.pl/vulnerabilities/isec-0021-uselib.txt
    CVE: CAN-2004-1235
    Author: Paul Starzetz <ihaquer@isec.pl>
    Date: Jan 07, 2005


    Locally exploitable flaws have been found in the Linux binary format
    loaders' uselib() functions that allow local users to gain root


    The Linux kernel provides a binary format loader layer to load (execute)
    programs of different binary formats like ELF or a.out and more. The
    kernel also provides a function named sys_uselib() to load a
    corresponding library. This function is dispatched to the current
    process's binary format handler and is basicaly a simplified mmap() code
    coupled with some header parsing code.

    An analyse of the uselib function load_elf_library() from binfmt_elf.c
    revealed a flaw in the handling of the library's brk segment (VMA). That
    segment is created with the current->mm->mmap_sem semaphore NOT held
    while modyfying the memory layout of the calling process. This can be
    used to disturb the memory management and gain elevated privileges. Also
    the binfmt_aout binary format loader code is affected in the same way.


    The vulnerable code resides for example in fs/binfmt_elf.c in your
    kernel source code tree:

    static int load_elf_library(struct file *file)
    [904] down_write(&current->mm->mmap_sem);
           error = do_mmap(file,
                         (elf_phdata->p_filesz +
                         PROT_READ | PROT_WRITE | PROT_EXEC,
                         MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
                         (elf_phdata->p_offset -
           if (error != ELF_PAGESTART(elf_phdata->p_vaddr))
                  goto out_free_ph;

           elf_bss = elf_phdata->p_vaddr + elf_phdata->p_filesz;

           len = ELF_PAGESTART(elf_phdata->p_filesz + elf_phdata->p_vaddr + ELF_MIN_ALIGN - 1);
           bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
           if (bss > len)
                  do_brk(len, bss - len);

    The line numbers are all valid for the 2.4.28 kernel version. As can be
    seen the mmap_sem is released prior to calling do_brk() in order to
    create the data section of the ELF library. On the other hand, looking
    into the code of sys_brk() from mm/mmap.c reveals that do_brk() must be
    called with the semaphore held.

    A short look into the code of do_brk() shows that:

    [1094] vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
           if (!vma)
                  return -ENOMEM;

           vma->vm_mm = mm;
           vma->vm_start = addr;
           vma->vm_end = addr + len;
           vma->vm_flags = flags;
           vma->vm_page_prot = protection_map[flags & 0x0f];
           vma->vm_ops = NULL;
           vma->vm_pgoff = 0;
           vma->vm_file = NULL;
           vma->vm_private_data = NULL;

           vma_link(mm, vma, prev, rb_link, rb_parent);

    where rb_link and rb_parent were both found by calling
    find_vma_prepare(). Obviously, if the kmem_cache_alloc() call sleeps,
    the newly created VMA descriptor may be inserted at wrong position
    because the process's VMA list and the VMA RB-tree may have been changed
    by another thread. This is absolutely enough to gain root privileges.

    We have found at least three different ways to exploit this
    vulnerability. The race condition can be easily won by consuming a big
    amount of memory. A proof of concept code exists but will not be
    released yet.


    Unprivileged local users can gain elevated (root) privileges.


    Paul Starzetz <ihaquer@isec.pl> has identified the vulnerability and
    performed further research. COPYING, DISTRIBUTION, AND MODIFICATION OF


    This document and all the information it contains are provided "as is",
    for educational purposes only, without warranty of any kind, whether
    express or implied.

    The authors reserve the right not to be responsible for the topicality,
    correctness, completeness or quality of the information provided in
    this document. Liability claims regarding damage caused by the use of
    any information provided, including any kind of information which is
    incomplete or incorrect, will therefore be rejected.


    Code attached.

    - ------------------------------------------------------------------------

    - --
    Paul Starzetz
    iSEC Security Research

    Version: GnuPG v1.0.7 (GNU/Linux)

    -----END PGP SIGNATURE-----


  • Next message: customer service mailbox: "[VulnWatch] iDEFENSE Security Advisory [IDEF0731] Exim auth_spa_server() Buffer Overflow Vulnerability"