• Jann Horn's avatar
    mm: lock_vma_under_rcu() must check vma->anon_vma under vma lock · 657b5146
    Jann Horn authored
    lock_vma_under_rcu() tries to guarantee that __anon_vma_prepare() can't
    be called in the VMA-locked page fault path by ensuring that
    vma->anon_vma is set.
    
    However, this check happens before the VMA is locked, which means a
    concurrent move_vma() can concurrently call unlink_anon_vmas(), which
    disassociates the VMA's anon_vma.
    
    This means we can get UAF in the following scenario:
    
      THREAD 1                   THREAD 2
      ========                   ========
      <page fault>
        lock_vma_under_rcu()
          rcu_read_lock()
          mas_walk()
          check vma->anon_vma
    
                                 mremap() syscall
                                   move_vma()
                                    vma_start_write()
                                     unlink_anon_vmas()
                                 <syscall end>
    
        handle_mm_fault()
          __handle_mm_fault()
            handle_pte_fault()
              do_pte_missing()
                do_anonymous_page()
                  anon_vma_prepare()
                    __anon_vma_prepare()
                      find_mergeable_anon_vma()
                        mas_walk() [looks up VMA X]
    
                                 munmap() syscall (deletes VMA X)
    
                        reusable_anon_vma() [called on freed VMA X]
    
    This is a security bug if you can hit it, although an attacker would
    have to win two races at once where the first race window is only a few
    instructions wide.
    
    This patch is based on some previous discussion with Linus Torvalds on
    the security list.
    
    Cc: stable@vger.kernel.org
    Fixes: 5e31275c ("mm: add per-VMA lock and helper functions to control it")
    Signed-off-by: default avatarJann Horn <jannh@google.com>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    657b5146
memory.c 165 KB