Commit 584f5bcb authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] mremap NULL pointer dereference fix

This is a cleaned-up version of a mremap() fix for "move_one_page()"
by Rajesh Venkatasubramanian <vrajesh@umich.edu>. We could use a NULL
"src" pointer.

Because while we do hold the MM semaphore over the whole sequence, the
destination page table allocation will possibly drop the page table
spinlock.  That in turn can cause a clean source page to be stolen by
page reclaim, causing the source-side "get_one_pte_map_nested()" to
return NULL the second time around even if it didn't on the first case.

So we just check "src" again, and get rid of the bogus TLB invalidate
while we're at it.
parent d90349aa
...@@ -135,15 +135,17 @@ move_one_page(struct vm_area_struct *vma, unsigned long old_addr, ...@@ -135,15 +135,17 @@ move_one_page(struct vm_area_struct *vma, unsigned long old_addr,
dst = alloc_one_pte_map(mm, new_addr); dst = alloc_one_pte_map(mm, new_addr);
if (src == NULL) if (src == NULL)
src = get_one_pte_map_nested(mm, old_addr); src = get_one_pte_map_nested(mm, old_addr);
error = copy_one_pte(vma, old_addr, src, dst, &pte_chain);
pte_unmap_nested(src);
pte_unmap(dst);
} else
/* /*
* Why do we need this flush ? If there is no pte for * Since alloc_one_pte_map can drop and re-acquire
* old_addr, then there must not be a pte for it as well. * page_table_lock, we should re-check the src entry...
*/ */
flush_tlb_page(vma, old_addr); if (src) {
error = copy_one_pte(vma, old_addr, src,
dst, &pte_chain);
pte_unmap_nested(src);
}
pte_unmap(dst);
}
spin_unlock(&mm->page_table_lock); spin_unlock(&mm->page_table_lock);
pte_chain_free(pte_chain); pte_chain_free(pte_chain);
out: out:
......
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