[PATCH] page_mkwrite caller race fix
After do_wp_page has tested page_mkwrite, it must release old_page after acquiring page table lock, not before: at some stage that ordering got reversed, leaving a (very unlikely) window in which old_page might be truncated, freed, and reused in the same position. Signed-off-by: Hugh Dickins <hugh@veritas.com> Acked-by: Nick Piggin <nickpiggin@yahoo.com.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
f05b6284ee
commit
c3704ceb4a
|
@ -1531,8 +1531,6 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||||
if (vma->vm_ops->page_mkwrite(vma, old_page) < 0)
|
if (vma->vm_ops->page_mkwrite(vma, old_page) < 0)
|
||||||
goto unwritable_page;
|
goto unwritable_page;
|
||||||
|
|
||||||
page_cache_release(old_page);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Since we dropped the lock we need to revalidate
|
* Since we dropped the lock we need to revalidate
|
||||||
* the PTE as someone else may have changed it. If
|
* the PTE as someone else may have changed it. If
|
||||||
|
@ -1541,6 +1539,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||||
*/
|
*/
|
||||||
page_table = pte_offset_map_lock(mm, pmd, address,
|
page_table = pte_offset_map_lock(mm, pmd, address,
|
||||||
&ptl);
|
&ptl);
|
||||||
|
page_cache_release(old_page);
|
||||||
if (!pte_same(*page_table, orig_pte))
|
if (!pte_same(*page_table, orig_pte))
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue