]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
mm: do not collapse stack gap into THP
authorMichal Hocko <mhocko@suse.com>
Thu, 25 May 2017 06:12:42 +0000 (08:12 +0200)
committerStefan Bader <stefan.bader@canonical.com>
Thu, 8 Jun 2017 09:59:34 +0000 (11:59 +0200)
Oleg has noticed that khugepaged will happilly collapse stack vma (as
long as it is not an early stack - see is_vma_temporary_stack) and
it might effectively remove the stack gap area as well because a larger
part of the stack vma is usually populated. The same applies to the
page fault handler.

Fix this by checking stack_guard_area when revalidating a VMA
in hugepage_vma_revalidate.  We do not want to hook/replace
is_vma_temporary_stack() check because THP might be still useful for
stack, all we need is excluding the gap from collapsing into a THP.

Also check the to-be-created THP in do_huge_pmd_anonymous_page to
make sure it is completely outside of the gap area because we we could
create THP covering the gap area.

CVE-2017-1000364

Noticed-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
mm/huge_memory.c
mm/khugepaged.c

index 49cb70b5993deddd13e54fda231f14cf414ce543..75719aa0443a322f8008f64459d52256df77a34e 100644 (file)
@@ -660,6 +660,9 @@ int do_huge_pmd_anonymous_page(struct vm_fault *vmf)
 
        if (haddr < vma->vm_start || haddr + HPAGE_PMD_SIZE > vma->vm_end)
                return VM_FAULT_FALLBACK;
+       if (stack_guard_area(vma, haddr) ||
+                       stack_guard_area(vma, haddr + HPAGE_PMD_SIZE))
+               return VM_FAULT_FALLBACK;
        if (unlikely(anon_vma_prepare(vma)))
                return VM_FAULT_OOM;
        if (unlikely(khugepaged_enter(vma, vma->vm_flags)))
index 77ae3239c3de17bfbf7ba29b56a5cb270611cfd8..16379e5943a6c2d09b825e5b9d5e67c7c69ffcda 100644 (file)
@@ -859,6 +859,10 @@ static int hugepage_vma_revalidate(struct mm_struct *mm, unsigned long address,
                return SCAN_ADDRESS_RANGE;
        if (!hugepage_vma_check(vma))
                return SCAN_VMA_CHECK;
+
+       /* never try to collapse stack gap */
+       if (stack_guard_area(vma, hstart) || stack_guard_area(vma, hend))
+               return SCAN_ADDRESS_RANGE;
        return 0;
 }