Re: Second critical mremap() bug found in all Linux kernels

From: Dan Yefimov (dan_at_D00M.integrate.com.ru)
Date: 02/19/04

  • Next message: Joseph M Hoffman: "[Full-Disclosure] Re: ASN.1 telephony critical infrastructure warning - VOIP"
    Date: Thu, 19 Feb 2004 07:24:43 +0300 (MSK)
    To: security@isec.pl
    
    
    

    On Wed, 18 Feb 2004, Paul Starzetz wrote:

    > -----BEGIN PGP SIGNED MESSAGE-----
    > Hash: SHA1
    >
    > Synopsis: Linux kernel do_mremap VMA limit local privilege escalation
    > vulnerability
    > Product: Linux kernel
    > Version: 2.2 up to 2.2.25, 2.4 up to 2.4.24, 2.6 up to 2.6.2
    > Vendor: http://www.kernel.org/
    > URL: http://isec.pl/vulnerabilities/isec-0014-mremap-unmap.txt
    > CVE: CAN-2004-0077
    > Author: Paul Starzetz <ihaquer@isec.pl>
    > Date: February 18, 2004
    >
    >
    > Issue:
    > ======
    >
    > A critical security vulnerability has been found in the Linux kernel
    > memory management code inside the mremap(2) system call due to missing
    > function return value check. This bug is completely unrelated to the
    > mremap bug disclosed on 05-01-2004 except concerning the same internal
    > kernel function code.
    >
    >
    > Details:
    > ========
    >
    > The Linux kernel manages a list of user addressable valid memory
    > locations on a per process basis. Every process owns a single linked
    > list of so called virtual memory area descriptors (called from now on
    > just VMAs). Every VMA describes the start of a valid memory region, its
    > length and moreover various memory flags like page protection.
    >
    > Every VMA in the list corresponds to a part of the process's page table.
    > The page table contains descriptors (in short page table entries PTEs)
    > of physical memory pages seen by the process. The VMA descriptor can be
    > thus understood as a high level description of a particular region of
    > the process's page table storing PTE properties like page R/W flag and
    > so on.
    >
    > The mremap() system call provides resizing (shrinking or growing) as
    > well as moving of existing virtual memory areas or any of its parts
    > across process's addressable space.
    >
    > Moving a part of the virtual memory from inside a VMA area to a new
    > location requires creation of a new VMA descriptor as well as copying
    > the underlying page table entries described by the VMA from the old to
    > the new location in the process's page table.
    >
    > To accomplish this task the do_mremap code calls the do_munmap()
    > internal kernel function to remove any potentially existing old memory
    > mapping in the new location as well as to remove the old virtual memory
    > mapping. Unfortunately the code doesn't test the return value of the
    > do_munmap() function which may fail if the maximum number of available
    > VMA descriptors has been exceeded. This happens if one tries to unmap
    > middle part of an existing memory mapping and the process's limit on the
    > number of VMAs has been reached (which is currently 65535).
    >
    > One of the possible situations can be illustrated with the following
    > picture. The corresponding page table entries (PTEs) have been marked
    > with o and x:
    >
    > Before mremap():
    >
    > (oooooooooooooooooooooooo) (xxxxxxxxxxxx)
    > [----------VMA1----------] [----VMA2----]
    > [REMAPPED-VMA] <---------------|
    >
    >
    > After mremap() without VMA limit:
    >
    > (oooo)(xxxxxxxxxxxx)(oooo)
    > [VMA3][REMAPPED-VMA][VMA4]
    >
    >
    > After mremap() but VMA limit:
    >
    > (ooooxxxxxxxxxxxxxxoooo)
    > [---------VMA1---------]
    > [REMAPPED-VMA]
    >
    >
    > After the maximum number of VMAs in the process's VMA list has been
    > reached do_munmap() will refuse to create the necessary VMA hole because
    > it would split the original VMA in two disjoint VMA areas exceeding the
    > VMA descriptor limit.
    >
    > Due to the missing return value check after trying to unmap the middle
    > of the VMA1 (this is the first invocation of do_munmap inside do_mremap
    > code) the corresponding page table entries from VMA2 are still inserted
    > into the page table location described by VMA1 thus being subject to
    > VMA1 page protection flags. It must be also mentioned that the original
    > PTEs in the VMA1 are lost thus leaving the corresponding page frames
    > unusable for ever.
    >
    > The kernel also tries to insert the overlapping VMA area into the VMA
    > descriptor list but this fails due to further checks in the low level
    > VMA manipulation code. The low level VMA list check in the 2.4 and 2.6
    > kernel versions just call BUG() therefore terminating the malicious
    > process.
    >
    > There are also two other unchecked calls to do_munmap() inside the
    > do_mremap() code and we believe that the second occurrence of unchecked
    > do_munmap is also exploitable. The second occurrence takes place if the
    > VMA to be remapped is beeing truncated in place. Note that do_munmap can
    > also fail on an exceptional low memory condition while trying to
    > allocate a VMA descriptor.
    >
    > We were able to create a robust proof-of-concept exploit code giving
    > full super-user privileges on all vulnerable kernel versions. The
    > exploit code will be released next week.
    >
    >
    > Impact:
    > =======
    >
    > Since no special privileges are required to use the mremap(2) system
    > call any process may use its unexpected behavior to disrupt the kernel
    > memory management subsystem.
    >
    > Proper exploitation of this vulnerability leads to local privilege
    > escalation giving an attacker full super-user privileges. The
    > vulnerability may also lead to a denial-of-service attack on the
    > available system memory.
    >
    > Tested and known to be vulnerable kernel versions are all <= 2.2.25, <=
    > 2.4.24 and <= 2.6.1. The 2.2.25 version of Linux kernel does not
    > recognize the MREMAP_FIXED flag but this does not prevent the bug from
    > being successfully exploited. All users are encouraged to patch all
    > vulnerable systems as soon as appropriate vendor patches are released.
    > There is no hotfix for this vulnerablity. Limited per user virtual
    > memory still permits do_munmap() to fail.
    >
    >
    > Credits:
    > ========
    >
    > Paul Starzetz <ihaquer@isec.pl> has identified the vulnerability and
    > performed further research. COPYING, DISTRIBUTION, AND MODIFICATION OF
    > INFORMATION PRESENTED HERE IS ALLOWED ONLY WITH EXPRESS PERMISSION OF
    > ONE OF THE AUTHORS.
    >
    >
    > Disclaimer:
    > ===========
    >
    > 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.
    >
    > - --
    > Paul Starzetz
    > iSEC Security Research
    > http://isec.pl/
    >
    > -----BEGIN PGP SIGNATURE-----
    > Version: GnuPG v1.0.7 (GNU/Linux)
    >
    > iD8DBQFAM1QzC+8U3Z5wpu4RAqXzAKCMOkFu1mXzzRgLyuFYp4ORpQCQDgCfe4M2
    > 3IjbGvzniOjv/Hc7KKAzMtU=
    > =GJds
    > -----END PGP SIGNATURE-----
    >
    >
    Attached patch fixes this bug for kernel 2.2.25. It should also apply cleanly to
    kernels since at least 2.2.21.

    -- 
        Sincerely Your, Dan.
    
    



  • Next message: Joseph M Hoffman: "[Full-Disclosure] Re: ASN.1 telephony critical infrastructure warning - VOIP"

    Relevant Pages