mm: pagewalk: Fix race between unmap and page walker
[ Upstream commit 8782fb61cc848364e1e1599d76d3c9dd58a1cc06 ]
The mmap lock protects the page walker from changes to the page tables
during the walk. However a read lock is insufficient to protect those
areas which don't have a VMA as munmap() detaches the VMAs before
downgrading to a read lock and actually tearing down PTEs/page tables.
For users of walk_page_range() the solution is to simply call pte_hole()
immediately without checking the actual page tables when a VMA is not
present. We now never call __walk_page_range() without a valid vma.
For walk_page_range_novma() the locking requirements are tightened to
require the mmap write lock to be taken, and then walking the pgd
directly with 'no_vma' set.
This in turn means that all page walkers either have a valid vma, or
it's that special 'novma' case for page table debugging. As a result,
all the odd '(!walk->vma && !walk->no_vma)' tests can be removed.
Fixes: dd2283f260
("mm: mmap: zap pages with read mmap_sem in munmap")
Reported-by: Jann Horn <jannh@google.com>
Signed-off-by: Steven Price <steven.price@arm.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Cc: Konstantin Khlebnikov <koct9i@gmail.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
5d0d46e625
commit
47a73e5e6b
@@ -141,13 +141,13 @@ void ptdump_walk_pgd(struct ptdump_state *st, struct mm_struct *mm, pgd_t *pgd)
|
||||
{
|
||||
const struct ptdump_range *range = st->range;
|
||||
|
||||
mmap_read_lock(mm);
|
||||
mmap_write_lock(mm);
|
||||
while (range->start != range->end) {
|
||||
walk_page_range_novma(mm, range->start, range->end,
|
||||
&ptdump_ops, pgd, st);
|
||||
range++;
|
||||
}
|
||||
mmap_read_unlock(mm);
|
||||
mmap_write_unlock(mm);
|
||||
|
||||
/* Flush out the last page */
|
||||
st->note_page(st, 0, -1, 0);
|
||||
|
Reference in New Issue
Block a user