Commit 941150a3 authored by Hugh Dickins's avatar Hugh Dickins Committed by Linus Torvalds

[PATCH] mbind: fix verify_pages pte_page

Strict mbind's check that pages already mapped are on right node has been
using pte_page without checking if pfn_valid, and without page_table_lock
to prevent spurious failures when try_to_unmap_one intervenes between the
pte_present and the pte_page.
Signed-off-by: default avatarHugh Dickins <hugh@veritas.com>
Cc: Andi Kleen <ak@muc.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 400e6514
...@@ -242,6 +242,9 @@ static int ...@@ -242,6 +242,9 @@ static int
verify_pages(struct mm_struct *mm, verify_pages(struct mm_struct *mm,
unsigned long addr, unsigned long end, unsigned long *nodes) unsigned long addr, unsigned long end, unsigned long *nodes)
{ {
int err = 0;
spin_lock(&mm->page_table_lock);
while (addr < end) { while (addr < end) {
struct page *p; struct page *p;
pte_t *pte; pte_t *pte;
...@@ -268,17 +271,23 @@ verify_pages(struct mm_struct *mm, ...@@ -268,17 +271,23 @@ verify_pages(struct mm_struct *mm,
} }
p = NULL; p = NULL;
pte = pte_offset_map(pmd, addr); pte = pte_offset_map(pmd, addr);
if (pte_present(*pte)) if (pte_present(*pte)) {
p = pte_page(*pte); unsigned long pfn = pte_pfn(*pte);
if (pfn_valid(pfn))
p = pfn_to_page(pfn);
}
pte_unmap(pte); pte_unmap(pte);
if (p) { if (p) {
unsigned nid = page_to_nid(p); unsigned nid = page_to_nid(p);
if (!test_bit(nid, nodes)) if (!test_bit(nid, nodes)) {
return -EIO; err = -EIO;
break;
}
} }
addr += PAGE_SIZE; addr += PAGE_SIZE;
} }
return 0; spin_unlock(&mm->page_table_lock);
return err;
} }
/* Step 1: check the range */ /* Step 1: check the range */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment