Skip to content

Commit f268f6c

Browse files
thejhakpm00
authored andcommitted
mm/khugepaged: invoke MMU notifiers in shmem/file collapse paths
Any codepath that zaps page table entries must invoke MMU notifiers to ensure that secondary MMUs (like KVM) don't keep accessing pages which aren't mapped anymore. Secondary MMUs don't hold their own references to pages that are mirrored over, so failing to notify them can lead to page use-after-free. I'm marking this as addressing an issue introduced in commit f3f0e1d ("khugepaged: add support of collapse for tmpfs/shmem pages"), but most of the security impact of this only came in commit 27e1f82 ("khugepaged: enable collapse pmd for pte-mapped THP"), which actually omitted flushes for the removal of present PTEs, not just for the removal of empty page tables. Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Fixes: f3f0e1d ("khugepaged: add support of collapse for tmpfs/shmem pages") Signed-off-by: Jann Horn <[email protected]> Acked-by: David Hildenbrand <[email protected]> Reviewed-by: Yang Shi <[email protected]> Cc: John Hubbard <[email protected]> Cc: Peter Xu <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 2ba99c5 commit f268f6c

File tree

1 file changed

+5
-0
lines changed

1 file changed

+5
-0
lines changed

mm/khugepaged.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,6 +1399,7 @@ static void collapse_and_free_pmd(struct mm_struct *mm, struct vm_area_struct *v
13991399
unsigned long addr, pmd_t *pmdp)
14001400
{
14011401
pmd_t pmd;
1402+
struct mmu_notifier_range range;
14021403

14031404
mmap_assert_write_locked(mm);
14041405
if (vma->vm_file)
@@ -1410,8 +1411,12 @@ static void collapse_and_free_pmd(struct mm_struct *mm, struct vm_area_struct *v
14101411
if (vma->anon_vma)
14111412
lockdep_assert_held_write(&vma->anon_vma->root->rwsem);
14121413

1414+
mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, NULL, mm, addr,
1415+
addr + HPAGE_PMD_SIZE);
1416+
mmu_notifier_invalidate_range_start(&range);
14131417
pmd = pmdp_collapse_flush(vma, addr, pmdp);
14141418
tlb_remove_table_sync_one();
1419+
mmu_notifier_invalidate_range_end(&range);
14151420
mm_dec_nr_ptes(mm);
14161421
page_table_check_pte_clear_range(mm, addr, pmd);
14171422
pte_free(mm, pmd_pgtable(pmd));

0 commit comments

Comments
 (0)