[RFC PATCH v2 35/47] userfaultfd: require UFFD_FEATURE_EXACT_ADDRESS when using HugeTLB HGM

From: James Houghton
Date: Fri Oct 21 2022 - 12:40:35 EST


To avoid bugs in userspace, we require that userspace provide
UFFD_FEATURE_EXACT_ADDRESS when using UFFD_FEATURE_MINOR_HUGETLBFS_HGM,
otherwise UFFDIO_API will fail with EINVAL.

The potential confusion is this: without EXACT_ADDRESS, the address
given in the userfaultfd message will be rounded down to the hugepage
size. Userspace may think that, because they're using HGM, just
UFFDIO_CONTINUE the interval [address, address+PAGE_SIZE), but for
faults that didn't occur in the first base page of the hugepage, this
won't resolve the fault. The only choice it has in this scenario is to
UFFDIO_CONTINUE the interval [address, address+hugepage_size), which
negates the purpose of using HGM in the first place.

By requiring userspace to provide UFFD_FEATURE_EXACT_ADDRESS, there is
no rounding, and userspace now has the information it needs to
appropriately resolve the fault.

Another potential solution here is to change the behavior when
UFFD_FEATURE_EXACT_ADDRESS is not provided: when HGM is enabled, start
rounding to PAGE_SIZE instead of to the hugepage size. I think requiring
UFFD_FEATURE_EXACT_ADDRESS is cleaner.

Signed-off-by: James Houghton <jthoughton@xxxxxxxxxx>
---
fs/userfaultfd.c | 11 +++++++++++
1 file changed, 11 insertions(+)

diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index 0204108e3882..c8f21f53e37d 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -1990,6 +1990,17 @@ static int userfaultfd_api(struct userfaultfd_ctx *ctx,
~(UFFD_FEATURE_MINOR_HUGETLBFS | UFFD_FEATURE_MINOR_SHMEM);
#ifndef CONFIG_HUGETLB_HIGH_GRANULARITY_MAPPING
uffdio_api.features &= ~UFFD_FEATURE_MINOR_HUGETLBFS_HGM;
+#else
+
+ ret = -EINVAL;
+ if ((uffdio_api.features & UFFD_FEATURE_MINOR_HUGETLBFS_HGM) &&
+ !(uffdio_api.features & UFFD_FEATURE_EXACT_ADDRESS))
+ /*
+ * UFFD_FEATURE_MINOR_HUGETLBFS_HGM is mostly
+ * useless without UFFD_FEATURE_EXACT_ADDRESS,
+ * so require userspace to provide both.
+ */
+ goto err_out;
#endif /* CONFIG_HUGETLB_HIGH_GRANULARITY_MAPPING */
#endif /* CONFIG_HAVE_ARCH_USERFAULTFD_MINOR */

--
2.38.0.135.g90850a2211-goog