Re: [PATCH v2 16/24] hugetlb/userfaultfd: Hook page faults for uffd write protection

From: Peter Xu
Date: Tue Apr 27 2021 - 20:07:40 EST


On Tue, Apr 27, 2021 at 12:13:09PM -0400, Peter Xu wrote:
> Hook up hugetlbfs_fault() with the capability to handle userfaultfd-wp faults.
>
> We do this slightly earlier than hugetlb_cow() so that we can avoid taking some
> extra locks that we definitely don't need.
>
> Reviewed-by: Mike Kravetz <mike.kravetz@xxxxxxxxxx>
> Signed-off-by: Peter Xu <peterx@xxxxxxxxxx>
> ---
> mm/hugetlb.c | 19 +++++++++++++++++++
> 1 file changed, 19 insertions(+)
>
> diff --git a/mm/hugetlb.c b/mm/hugetlb.c
> index 629aa4c2259c8..8e234ee9a15e2 100644
> --- a/mm/hugetlb.c
> +++ b/mm/hugetlb.c
> @@ -4802,6 +4802,25 @@ vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
> if (unlikely(!pte_same(entry, huge_ptep_get(ptep))))
> goto out_ptl;
>
> + /* Handle userfault-wp first, before trying to lock more pages */
> + if (userfaultfd_pte_wp(vma, huge_ptep_get(ptep)) &&

I'm going to change this to:

- if (userfaultfd_pte_wp(vma, huge_ptep_get(ptep)) &&
+ if (userfaultfd_wp(vma) && huge_pte_uffd_wp(huge_ptep_get(ptep)) &&

As strictly speaking it's not right to use userfaultfd_pte_wp() directly on a
huge pte... Currently huge_pte_uffd_wp() is missing in this version (which is
still pte_uffd_wp() anyways), but I'll add a separate patch to introduce all
these helpers (also mention about what arch should do when the huge pte is not
handled the same way as small pte). I'll try to keep Mike's R-b as this change
should be trivial, or please shoot. Thanks,

> + (flags & FAULT_FLAG_WRITE) && !huge_pte_write(entry)) {
> + struct vm_fault vmf = {
> + .vma = vma,
> + .address = haddr,
> + .flags = flags,
> + };
> +
> + spin_unlock(ptl);
> + if (pagecache_page) {
> + unlock_page(pagecache_page);
> + put_page(pagecache_page);
> + }
> + mutex_unlock(&hugetlb_fault_mutex_table[hash]);
> + i_mmap_unlock_read(mapping);
> + return handle_userfault(&vmf, VM_UFFD_WP);
> + }
> +
> /*
> * hugetlb_cow() requires page locks of pte_page(entry) and
> * pagecache_page, so here we need take the former one
> --
> 2.26.2
>

--
Peter Xu