2.6.25-stable review patch. If anyone has any objections, please let us know. ------------------ From: David Gibson Correct hash flushing from huge_ptep_set_wrprotect() [stable tree version] A fix for incorrect flushing of the hash page table at fork() for hugepages was recently committed as 86df86424939d316b1f6cfac1b6204f0c7dee317. Without this fix, a process can make a MAP_PRIVATE hugepage mapping, then fork() and have writes to the mapping after the fork() pollute the child's version. Unfortunately this bug also exists in the stable branch. In fact in that case copy_hugetlb_page_range() from mm/hugetlb.c calls ptep_set_wrprotect() directly, the hugepage variant hook huge_ptep_set_wrprotect() doesn't even exist. The patch below is a port of the fix to the stable25/master branch. It introduces a huge_ptep_set_wrprotect() call, but this is #defined to be equal to ptep_set_wrprotect() unless the arch defines its own version and sets __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT. This arch preprocessor flag is kind of nasty, but it seems the sanest way to introduce this fix with minimum risk of breaking other archs for whom prep_set_wprotect() is suitable for hugepages. Signed-off-by: Andy Whitcroft Signed-off-by: David Gibson Signed-off-by: Greg Kroah-Hartman --- include/asm-powerpc/pgtable-ppc64.h | 11 +++++++++++ mm/hugetlb.c | 6 +++++- 2 files changed, 16 insertions(+), 1 deletion(-) --- a/include/asm-powerpc/pgtable-ppc64.h +++ b/include/asm-powerpc/pgtable-ppc64.h @@ -311,6 +311,17 @@ static inline void ptep_set_wrprotect(st old = pte_update(mm, addr, ptep, _PAGE_RW, 0); } +#define __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT +static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, + unsigned long addr, pte_t *ptep) +{ + unsigned long old; + + if ((pte_val(*ptep) & _PAGE_RW) == 0) + return; + old = pte_update(mm, addr, ptep, _PAGE_RW, 1); +} + /* * We currently remove entries from the hashtable regardless of whether * the entry was young or dirty. The generic routines only flush if the --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -738,6 +738,10 @@ static void set_huge_ptep_writable(struc } +#ifndef __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT +#define huge_ptep_set_wrprotect ptep_set_wrprotect +#endif + int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, struct vm_area_struct *vma) { @@ -764,7 +768,7 @@ int copy_hugetlb_page_range(struct mm_st spin_lock(&src->page_table_lock); if (!pte_none(*src_pte)) { if (cow) - ptep_set_wrprotect(src, addr, src_pte); + huge_ptep_set_wrprotect(src, addr, src_pte); entry = *src_pte; ptepage = pte_page(entry); get_page(ptepage); -- -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/