Skip to content
  • Hugh Dickins's avatar
    mm: fix race between mremap and removing migration entry · 6b2f66dc
    Hugh Dickins authored
    commit 486cf46f
    
     upstream.
    
    I don't usually pay much attention to the stale "? " addresses in
    stack backtraces, but this lucky report from Pawel Sikora hints that
    mremap's move_ptes() has inadequate locking against page migration.
    
     3.0 BUG_ON(!PageLocked(p)) in migration_entry_to_page():
     kernel BUG at include/linux/swapops.h:105!
     RIP: 0010:[<ffffffff81127b76>]  [<ffffffff81127b76>]
                           migration_entry_wait+0x156/0x160
      [<ffffffff811016a1>] handle_pte_fault+0xae1/0xaf0
      [<ffffffff810feee2>] ? __pte_alloc+0x42/0x120
      [<ffffffff8112c26b>] ? do_huge_pmd_anonymous_page+0xab/0x310
      [<ffffffff81102a31>] handle_mm_fault+0x181/0x310
      [<ffffffff81106097>] ? vma_adjust+0x537/0x570
      [<ffffffff81424bed>] do_page_fault+0x11d/0x4e0
      [<ffffffff81109a05>] ? do_mremap+0x2d5/0x570
      [<ffffffff81421d5f>] page_fault+0x1f/0x30
    
    mremap's down_write of mmap_sem, together with i_mmap_mutex or lock,
    and pagetable locks, were good enough before page migration (with its
    requirement that every migration entry be found) came in, and enough
    while migration always held mmap_sem; but not enough nowadays, when
    there's memory hotremove and compaction.
    
    The danger is that move_ptes() lets a migration entry dodge around
    behind remove_migration_pte()'s back, so it's in the old location when
    looking at the new, then in the new location when looking at the old.
    
    Either mremap's move_ptes() must additionally take anon_vma lock(), or
    migration's remove_migration_pte() must stop peeking for is_swap_entry()
    before it takes pagetable lock.
    
    Consensus chooses the latter: we prefer to add overhead to migration
    than to mremapping, which gets used by JVMs and by exec stack setup.
    
    Reported-and-tested-by: default avatarPaweł Sikora <pluto@agmk.net>
    Signed-off-by: default avatarHugh Dickins <hughd@google.com>
    Acked-by: default avatarAndrea Arcangeli <aarcange@redhat.com>
    Acked-by: default avatarMel Gorman <mgorman@suse.de>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
    6b2f66dc