From: Sasha Levin Date: Tue, 8 Jun 2021 14:27:15 +0000 (-0400) Subject: Fixes for 4.19 X-Git-Tag: v4.4.272~32^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=14c9c9621dc6bf7c35fd39c0c158c53f3910e7f2;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 4.19 Signed-off-by: Sasha Levin --- diff --git a/queue-4.19/mm-hugetlb-fix-simple-resv_huge_pages-underflow-on-u.patch b/queue-4.19/mm-hugetlb-fix-simple-resv_huge_pages-underflow-on-u.patch new file mode 100644 index 00000000000..8399c94ef10 --- /dev/null +++ b/queue-4.19/mm-hugetlb-fix-simple-resv_huge_pages-underflow-on-u.patch @@ -0,0 +1,82 @@ +From a4d7d806f90e3b6216041cac551eb6363f0d6681 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Jun 2021 20:01:36 -0700 +Subject: mm, hugetlb: fix simple resv_huge_pages underflow on UFFDIO_COPY + +From: Mina Almasry + +[ Upstream commit d84cf06e3dd8c5c5b547b5d8931015fc536678e5 ] + +The userfaultfd hugetlb tests cause a resv_huge_pages underflow. This +happens when hugetlb_mcopy_atomic_pte() is called with !is_continue on +an index for which we already have a page in the cache. When this +happens, we allocate a second page, double consuming the reservation, +and then fail to insert the page into the cache and return -EEXIST. + +To fix this, we first check if there is a page in the cache which +already consumed the reservation, and return -EEXIST immediately if so. + +There is still a rare condition where we fail to copy the page contents +AND race with a call for hugetlb_no_page() for this index and again we +will underflow resv_huge_pages. That is fixed in a more complicated +patch not targeted for -stable. + +Test: + + Hacked the code locally such that resv_huge_pages underflows produce a + warning, then: + + ./tools/testing/selftests/vm/userfaultfd hugetlb_shared 10 + 2 /tmp/kokonut_test/huge/userfaultfd_test && echo test success + ./tools/testing/selftests/vm/userfaultfd hugetlb 10 + 2 /tmp/kokonut_test/huge/userfaultfd_test && echo test success + +Both tests succeed and produce no warnings. After the test runs number +of free/resv hugepages is correct. + +[mike.kravetz@oracle.com: changelog fixes] + +Link: https://lkml.kernel.org/r/20210528004649.85298-1-almasrymina@google.com +Fixes: 8fb5debc5fcd ("userfaultfd: hugetlbfs: add hugetlb_mcopy_atomic_pte for userfaultfd support") +Signed-off-by: Mina Almasry +Reviewed-by: Mike Kravetz +Cc: Axel Rasmussen +Cc: Peter Xu +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + mm/hugetlb.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 2f769a661568..c69f12e4c149 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -4154,10 +4154,20 @@ int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, + struct page *page; + + if (!*pagep) { +- ret = -ENOMEM; ++ /* If a page already exists, then it's UFFDIO_COPY for ++ * a non-missing case. Return -EEXIST. ++ */ ++ if (vm_shared && ++ hugetlbfs_pagecache_present(h, dst_vma, dst_addr)) { ++ ret = -EEXIST; ++ goto out; ++ } ++ + page = alloc_huge_page(dst_vma, dst_addr, 0); +- if (IS_ERR(page)) ++ if (IS_ERR(page)) { ++ ret = -ENOMEM; + goto out; ++ } + + ret = copy_huge_page_from_user(page, + (const void __user *) src_addr, +-- +2.30.2 + diff --git a/queue-4.19/series b/queue-4.19/series index f8b4ffc2ad2..badbb493958 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -36,3 +36,4 @@ btrfs-mark-ordered-extent-and-inode-with-error-if-we-fail-to-finish.patch btrfs-fix-error-handling-in-btrfs_del_csums.patch btrfs-return-errors-from-btrfs_del_csums-in-cleanup_ref_head.patch btrfs-fixup-error-handling-in-fixup_inode_link_counts.patch +mm-hugetlb-fix-simple-resv_huge_pages-underflow-on-u.patch