UPSTREAM: 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.

Bug: 245812080
Signed-off-by: Jann Horn <jannh@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
(cherry picked from commit 3998dc50ebdc127ae79b10992856fb76debc2005)
Signed-off-by: Lee Jones <joneslee@google.com>
Change-Id: Ib8ddb51815e53f42daec5d98a196866a078a7550
This commit is contained in:
Jann Horn 2022-09-15 16:25:19 +02:00 committed by Lee Jones
parent 4a5337dfb3
commit 6d1487a4aa

View File

@ -2611,6 +2611,7 @@ static void unmap_region(struct mm_struct *mm,
{ {
struct vm_area_struct *next = prev ? prev->vm_next : mm->mmap; struct vm_area_struct *next = prev ? prev->vm_next : mm->mmap;
struct mmu_gather tlb; struct mmu_gather tlb;
struct vm_area_struct *cur_vma;
lru_add_drain(); lru_add_drain();
tlb_gather_mmu(&tlb, mm, start, end); tlb_gather_mmu(&tlb, mm, start, end);
@ -2625,8 +2626,12 @@ static void unmap_region(struct mm_struct *mm,
* concurrent flush in this region has to be coming through the rmap, * concurrent flush in this region has to be coming through the rmap,
* and we synchronize against that using the rmap lock. * and we synchronize against that using the rmap lock.
*/ */
if ((vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP)) != 0) for (cur_vma = vma; cur_vma; cur_vma = cur_vma->vm_next) {
tlb_flush_mmu(&tlb); 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, free_pgtables(&tlb, vma, prev ? prev->vm_end : FIRST_USER_ADDRESS,
next ? next->vm_start : USER_PGTABLES_CEILING); next ? next->vm_start : USER_PGTABLES_CEILING);