summaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorJann Horn <jannh@google.com>2022-08-31 21:13:48 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-09-05 10:25:05 +0200
commitb8a54a2a45feacbc96065e5d6b9a1cbee2aa1e9d (patch)
tree108792c8fe43c5a21a9a60b62e17822ca621365b /mm
parent1678ca35b80a94d474fdc31e2497ce5d7ed52512 (diff)
downloadlinux-stable-b8a54a2a45feacbc96065e5d6b9a1cbee2aa1e9d.tar.gz
linux-stable-b8a54a2a45feacbc96065e5d6b9a1cbee2aa1e9d.tar.bz2
linux-stable-b8a54a2a45feacbc96065e5d6b9a1cbee2aa1e9d.zip
mm: Force TLB flush for PFNMAP mappings before unlink_file_vma()
commit b67fbebd4cf980aecbcc750e1462128bffe8ae15 upstream. Some drivers rely on having all VMAs through which a PFN might be accessible listed in the rmap for correctness. However, on X86, it was possible for a VMA with stale TLB entries to not be listed in the rmap. This was fixed in mainline with commit b67fbebd4cf9 ("mmu_gather: Force tlb-flush VM_PFNMAP vmas"), but that commit relies on preceding refactoring in commit 18ba064e42df3 ("mmu_gather: Let there be one tlb_{start,end}_vma() implementation") and commit 1e9fdf21a4339 ("mmu_gather: Remove per arch tlb_{start,end}_vma()"). This patch provides equivalent protection without needing that refactoring, by forcing a TLB flush between removing PTEs in unmap_vmas() and the call to unlink_file_vma() in free_pgtables(). [This is a stable-specific rewrite of the upstream commit!] Signed-off-by: Jann Horn <jannh@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/mmap.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/mm/mmap.c b/mm/mmap.c
index ca37b4b6841d..17caf44807de 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2529,6 +2529,18 @@ static void unmap_region(struct mm_struct *mm,
tlb_gather_mmu(&tlb, mm, start, end);
update_hiwater_rss(mm);
unmap_vmas(&tlb, vma, start, end);
+
+ /*
+ * Ensure we have no stale TLB entries by the time this mapping is
+ * removed from the rmap.
+ * Note that we don't have to worry about nested flushes here because
+ * we're holding the mm semaphore for removing the mapping - so any
+ * concurrent flush in this region has to be coming through the rmap,
+ * and we synchronize against that using the rmap lock.
+ */
+ if ((vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP)) != 0)
+ tlb_flush_mmu(&tlb);
+
free_pgtables(&tlb, vma, prev ? prev->vm_end : FIRST_USER_ADDRESS,
next ? next->vm_start : USER_PGTABLES_CEILING);
tlb_finish_mmu(&tlb, start, end);