On Thu, 9 Sep 2021 18:22:40 +0200 David Hildenbrand <david@xxxxxxxxxx> wrote: > We should not walk/touch page tables outside of VMA boundaries when > holding only the mmap sem in read mode. Evil user space can modify the > VMA layout just before this function runs and e.g., trigger races with > page table removal code since commit dd2283f2605e ("mm: mmap: zap pages > with read mmap_sem in munmap"). The pure prescence in our guest_to_host > radix tree does not imply that there is a VMA. > > Further, we should not allocate page tables (via get_locked_pte()) outside > of VMA boundaries: if evil user space decides to map hugetlbfs to these > ranges, bad things will happen because we suddenly have PTE or PMD page > tables where we shouldn't have them. > > Similarly, we have to check if we suddenly find a hugetlbfs VMA, before > calling get_locked_pte(). > > Note that gmap_discard() is different: > zap_page_range()->unmap_single_vma() makes sure to stay within VMA > boundaries. > > Fixes: b31288fa83b2 ("s390/kvm: support collaborative memory management") > Signed-off-by: David Hildenbrand <david@xxxxxxxxxx> Reviewed-by: Claudio Imbrenda <imbrenda@xxxxxxxxxxxxx> > --- > arch/s390/mm/gmap.c | 6 ++++++ > 1 file changed, 6 insertions(+) > > diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c > index 9bb2c7512cd5..b6b56cd4ca64 100644 > --- a/arch/s390/mm/gmap.c > +++ b/arch/s390/mm/gmap.c > @@ -673,6 +673,7 @@ EXPORT_SYMBOL_GPL(gmap_fault); > */ > void __gmap_zap(struct gmap *gmap, unsigned long gaddr) > { > + struct vm_area_struct *vma; > unsigned long vmaddr; > spinlock_t *ptl; > pte_t *ptep; > @@ -682,6 +683,11 @@ void __gmap_zap(struct gmap *gmap, unsigned long gaddr) > gaddr >> PMD_SHIFT); > if (vmaddr) { > vmaddr |= gaddr & ~PMD_MASK; > + > + vma = vma_lookup(gmap->mm, vmaddr); > + if (!vma || is_vm_hugetlb_page(vma)) > + return; > + > /* Get pointer to the page table entry */ > ptep = get_locked_pte(gmap->mm, vmaddr, &ptl); > if (likely(ptep))