Skip to contentSkip to conversation

Patch "mm/hugetlb.c: __get_user_pages ignores certain follow_hugetlb_page errors" has been added to the 4.12-stable tree

PATCH [email protected] 1 participant 1 message Aug 7, 2017

Subsystems (3)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

mm/hugetlb.c: __get_user_pages ignores certain follow_hugetlb_page errors

to the 4.12-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
mm-hugetlb.c-__get_user_pages-ignores-certain-follow_hugetlb_page-errors.patch
and it can be found in the queue-4.12 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

Quoted 1 line

From 2be7cfed995e25de1ffaffe14cc065b7ffb528e0 Mon Sep 17 00:00:00 2001

From: Daniel Jordan <[email protected]>
Date: Wed, 2 Aug 2017 13:31:47 -0700
Subject: mm/hugetlb.c: __get_user_pages ignores certain follow_hugetlb_page errors

From: Daniel Jordan <[email protected]>

commit 2be7cfed995e25de1ffaffe14cc065b7ffb528e0 upstream.

Commit 9a291a7c9428 ("mm/hugetlb: report -EHWPOISON not -EFAULT when FOLL_HWPOISON is specified") causes __get_user_pages to ignore certain errors from follow_hugetlb_page. After such error, __get_user_pages subsequently calls faultin_page on the same VMA and start address that follow_hugetlb_page failed on instead of returning the error immediately as it should.

In follow_hugetlb_page, when hugetlb_fault returns a value covered under VM_FAULT_ERROR, follow_hugetlb_page returns it without setting nr_pages to 0 as __get_user_pages expects in this case, which causes the following to happen in __get_user_pages: the "while (nr_pages)" check succeeds, we skip the "if (!vma..." check because we got a VMA the last time around, we find no page with follow_page_mask, and we call faultin_page, which calls hugetlb_fault for the second time.

This issue also slightly changes how __get_user_pages works. Before, it only returned error if it had made no progress (i = 0). But now, follow_hugetlb_page can clobber "i" with an error code since its new return path doesn't check for progress. So if "i" is nonzero before a failing call to follow_hugetlb_page, that indication of progress is lost and __get_user_pages can return error even if some pages were successfully pinned.

To fix this, change follow_hugetlb_page so that it updates nr_pages, allowing __get_user_pages to fail immediately and restoring the "error only if no progress" behavior to __get_user_pages.

Tested that __get_user_pages returns when expected on error from hugetlb_fault in follow_hugetlb_page.

Fixes 9a291a7c9428 ("mm/hugetlb: report -EHWPOISON not -EFAULT when FOLL_HWPOISON is specified")
Cc Andrea Arcangeli <[email protected]>
Cc "Aneesh Kumar K.V" <[email protected]>
Cc Gerald Schaefer <[email protected]>
Cc James Morse <[email protected]>
Cc "Kirill A. Shutemov" <[email protected]>
Cc Michal Hocko <[email protected]>
Cc Mike Kravetz <[email protected]>
Cc Naoya Horiguchi <[email protected]>
Cc zhong jiang <[email protected]>
---
 mm/hugetlb.c |    9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)
mm/hugetlb.c +3 -6
@@ -4095,6 +4095,7 @@ long follow_hugetlb_page(struct mm_struc
 	unsigned long vaddr = *position;
 	unsigned long remainder = *nr_pages;
 	struct hstate *h = hstate_vma(vma);
+	int err = -EFAULT;
 
 	while (vaddr < vma->vm_end && remainder) {
 		pte_t *pte;
@@ -4170,11 +4171,7 @@ long follow_hugetlb_page(struct mm_struc
 			}
 			ret = hugetlb_fault(mm, vma, vaddr, fault_flags);
 			if (ret & VM_FAULT_ERROR) {
-				int err = vm_fault_to_errno(ret, flags);
-
-				if (err)
-					return err;
-
+				err = vm_fault_to_errno(ret, flags);
 				remainder = 0;
 				break;
 			}
@@ -4229,7 +4226,7 @@ same_page:
 	 */
 	*position = vaddr;
 
-	return i ? i : -EFAULT;
+	return i ? i : err;
 }
 
 #ifndef __HAVE_ARCH_FLUSH_HUGETLB_TLB_RANGE

Patches currently in stable-queue which might be from [email protected] are

queue-4.12/mm-hugetlb.c-__get_user_pages-ignores-certain-follow_hugetlb_page-errors.patch