Skip to content

Commit 1013af4

Browse files
thejhakpm00
authored andcommitted
mm/hugetlb: fix huge_pmd_unshare() vs GUP-fast race
huge_pmd_unshare() drops a reference on a page table that may have previously been shared across processes, potentially turning it into a normal page table used in another process in which unrelated VMAs can afterwards be installed. If this happens in the middle of a concurrent gup_fast(), gup_fast() could end up walking the page tables of another process. While I don't see any way in which that immediately leads to kernel memory corruption, it is really weird and unexpected. Fix it with an explicit broadcast IPI through tlb_remove_table_sync_one(), just like we do in khugepaged when removing page tables for a THP collapse. Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Fixes: 39dde65 ("[PATCH] shared page table for hugetlb page") Signed-off-by: Jann Horn <[email protected]> Reviewed-by: Lorenzo Stoakes <[email protected]> Cc: Liam Howlett <[email protected]> Cc: Muchun Song <[email protected]> Cc: Oscar Salvador <[email protected]> Cc: Vlastimil Babka <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 081056d commit 1013af4

File tree

1 file changed

+7
-0
lines changed

1 file changed

+7
-0
lines changed

mm/hugetlb.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7629,6 +7629,13 @@ int huge_pmd_unshare(struct mm_struct *mm, struct vm_area_struct *vma,
76297629
return 0;
76307630

76317631
pud_clear(pud);
7632+
/*
7633+
* Once our caller drops the rmap lock, some other process might be
7634+
* using this page table as a normal, non-hugetlb page table.
7635+
* Wait for pending gup_fast() in other threads to finish before letting
7636+
* that happen.
7637+
*/
7638+
tlb_remove_table_sync_one();
76327639
ptdesc_pmd_pts_dec(virt_to_ptdesc(ptep));
76337640
mm_dec_nr_pmds(mm);
76347641
return 1;

0 commit comments

Comments
 (0)