• Brian Geffon's avatar
    mm: Fix MREMAP_DONTUNMAP accounting on VMA merge · dadbd85f
    Brian Geffon authored
    When remapping a mapping where a portion of a VMA is remapped
    into another portion of the VMA it can cause the VMA to become
    split. During the copy_vma operation the VMA can actually
    be remerged if it's an anonymous VMA whose pages have not yet
    been faulted. This isn't normally a problem because at the end
    of the remap the original portion is unmapped causing it to
    become split again.
    
    However, MREMAP_DONTUNMAP leaves that original portion in place which
    means that the VMA which was split and then remerged is not actually
    split at the end of the mremap. This patch fixes a bug where
    we don't detect that the VMAs got remerged and we end up
    putting back VM_ACCOUNT on the next mapping which is completely
    unreleated. When that next mapping is unmapped it results in
    incorrectly unaccounting for the memory which was never accounted,
    and eventually we will underflow on the memory comittment.
    
    There is also another issue which is similar, we're currently
    accouting for the number of pages in the new_vma but that's wrong.
    We need to account for the length of the remap operation as that's
    all that is being added. If there was a mapping already at that
    location its comittment would have been adjusted as part of
    the munmap at the start of the mremap.
    
    A really simple repro can be seen in:
    https://gist.github.com/bgaff/e101ce99da7d9a8c60acc641d07f312c
    
    Fixes: e346b381 ("mm/mremap: add MREMAP_DONTUNMAP to mremap()")
    Reported-by: default avatarsyzbot <syzkaller@googlegroups.com>
    Signed-off-by: default avatarBrian Geffon <bgeffon@google.com>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    dadbd85f
mremap.c 21.4 KB