From: Hugh Dickins Date: Wed, 19 Oct 2011 19:50:35 +0000 (-0700) Subject: mm: fix race between mremap and removing migration entry X-Git-Tag: v3.1~10 X-Git-Url: http://git.openpandora.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=486cf46f3f9be5f2a966016c1a8fe01e32cde09e;p=pandora-kernel.git mm: fix race between mremap and removing migration entry 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:[] [] migration_entry_wait+0x156/0x160 [] handle_pte_fault+0xae1/0xaf0 [] ? __pte_alloc+0x42/0x120 [] ? do_huge_pmd_anonymous_page+0xab/0x310 [] handle_mm_fault+0x181/0x310 [] ? vma_adjust+0x537/0x570 [] do_page_fault+0x11d/0x4e0 [] ? do_mremap+0x2d5/0x570 [] 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: Paweł Sikora Signed-off-by: Hugh Dickins Acked-by: Andrea Arcangeli Acked-by: Mel Gorman Cc: stable@vger.kernel.org Signed-off-by: Linus Torvalds --- Reading git-diff-tree failed