summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJann Horn <jannh@google.com>2022-09-15 16:25:19 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-09-20 11:51:30 +0200
commit25a9bf46fb74c28d9ccf3360965cdf31f13cea0d (patch)
tree53e8ad261d5d991be0aff99a90f994ecc13476ad
parent5df8b473517762e16c5a97c25941897640926a63 (diff)
downloadlinux-stable-25a9bf46fb74c28d9ccf3360965cdf31f13cea0d.tar.gz
linux-stable-25a9bf46fb74c28d9ccf3360965cdf31f13cea0d.tar.bz2
linux-stable-25a9bf46fb74c28d9ccf3360965cdf31f13cea0d.zip
mm: Fix TLB flush for not-first PFNMAP mappings in unmap_region()
This is a stable-specific patch. I botched the stable-specific rewrite of commit b67fbebd4cf98 ("mmu_gather: Force tlb-flush VM_PFNMAP vmas"): As Hugh pointed out, unmap_region() actually operates on a list of VMAs, and the variable "vma" merely points to the first VMA in that list. So if we want to check whether any of the VMAs we're operating on is PFNMAP or MIXEDMAP, we have to iterate through the list and check each VMA. Signed-off-by: Jann Horn <jannh@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--mm/mmap.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/mm/mmap.c b/mm/mmap.c
index 17caf44807de..e230e08d47b8 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2524,6 +2524,7 @@ static void unmap_region(struct mm_struct *mm,
{
struct vm_area_struct *next = prev ? prev->vm_next : mm->mmap;
struct mmu_gather tlb;
+ struct vm_area_struct *cur_vma;
lru_add_drain();
tlb_gather_mmu(&tlb, mm, start, end);
@@ -2538,8 +2539,12 @@ static void unmap_region(struct mm_struct *mm,
* 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);
+ for (cur_vma = vma; cur_vma; cur_vma = cur_vma->vm_next) {
+ if ((cur_vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP)) != 0) {
+ tlb_flush_mmu(&tlb);
+ break;
+ }
+ }
free_pgtables(&tlb, vma, prev ? prev->vm_end : FIRST_USER_ADDRESS,
next ? next->vm_start : USER_PGTABLES_CEILING);