lkml.org 
[lkml]   [2022]   [Apr]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v8 05/23] mm/shmem: Take care of UFFDIO_COPY_MODE_WP
    Date
    Pass wp_copy into shmem_mfill_atomic_pte() through the stack, then apply the
    UFFD_WP bit properly when the UFFDIO_COPY on shmem is with UFFDIO_COPY_MODE_WP.
    wp_copy lands mfill_atomic_install_pte() finally.

    Note: we must do pte_wrprotect() if !writable in mfill_atomic_install_pte(), as
    mk_pte() could return a writable pte (e.g., when VM_SHARED on a shmem file).

    Signed-off-by: Peter Xu <peterx@redhat.com>
    ---
    include/linux/shmem_fs.h | 4 ++--
    mm/shmem.c | 4 ++--
    mm/userfaultfd.c | 23 ++++++++++++++++++-----
    3 files changed, 22 insertions(+), 9 deletions(-)

    diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
    index 3e915cc550bc..a68f982f22d1 100644
    --- a/include/linux/shmem_fs.h
    +++ b/include/linux/shmem_fs.h
    @@ -145,11 +145,11 @@ extern int shmem_mfill_atomic_pte(struct mm_struct *dst_mm, pmd_t *dst_pmd,
    struct vm_area_struct *dst_vma,
    unsigned long dst_addr,
    unsigned long src_addr,
    - bool zeropage,
    + bool zeropage, bool wp_copy,
    struct page **pagep);
    #else /* !CONFIG_SHMEM */
    #define shmem_mfill_atomic_pte(dst_mm, dst_pmd, dst_vma, dst_addr, \
    - src_addr, zeropage, pagep) ({ BUG(); 0; })
    + src_addr, zeropage, wp_copy, pagep) ({ BUG(); 0; })
    #endif /* CONFIG_SHMEM */
    #endif /* CONFIG_USERFAULTFD */

    diff --git a/mm/shmem.c b/mm/shmem.c
    index 7004c7f55716..9efb8a96d75e 100644
    --- a/mm/shmem.c
    +++ b/mm/shmem.c
    @@ -2319,7 +2319,7 @@ int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
    struct vm_area_struct *dst_vma,
    unsigned long dst_addr,
    unsigned long src_addr,
    - bool zeropage,
    + bool zeropage, bool wp_copy,
    struct page **pagep)
    {
    struct inode *inode = file_inode(dst_vma->vm_file);
    @@ -2392,7 +2392,7 @@ int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
    goto out_release;

    ret = mfill_atomic_install_pte(dst_mm, dst_pmd, dst_vma, dst_addr,
    - page, true, false);
    + page, true, wp_copy);
    if (ret)
    goto out_delete_from_cache;

    diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
    index dae25d985d15..b1c875b77fbb 100644
    --- a/mm/userfaultfd.c
    +++ b/mm/userfaultfd.c
    @@ -77,10 +77,19 @@ int mfill_atomic_install_pte(struct mm_struct *dst_mm, pmd_t *dst_pmd,
    * Always mark a PTE as write-protected when needed, regardless of
    * VM_WRITE, which the user might change.
    */
    - if (wp_copy)
    + if (wp_copy) {
    _dst_pte = pte_mkuffd_wp(_dst_pte);
    - else if (writable)
    + writable = false;
    + }
    +
    + if (writable)
    _dst_pte = pte_mkwrite(_dst_pte);
    + else
    + /*
    + * We need this to make sure write bit removed; as mk_pte()
    + * could return a pte with write bit set.
    + */
    + _dst_pte = pte_wrprotect(_dst_pte);

    dst_pte = pte_offset_map_lock(dst_mm, dst_pmd, dst_addr, &ptl);

    @@ -95,7 +104,12 @@ int mfill_atomic_install_pte(struct mm_struct *dst_mm, pmd_t *dst_pmd,
    }

    ret = -EEXIST;
    - if (!pte_none(*dst_pte))
    + /*
    + * We allow to overwrite a pte marker: consider when both MISSING|WP
    + * registered, we firstly wr-protect a none pte which has no page cache
    + * page backing it, then access the page.
    + */
    + if (!pte_none_mostly(*dst_pte))
    goto out_unlock;

    if (page_in_cache) {
    @@ -479,11 +493,10 @@ static __always_inline ssize_t mfill_atomic_pte(struct mm_struct *dst_mm,
    err = mfill_zeropage_pte(dst_mm, dst_pmd,
    dst_vma, dst_addr);
    } else {
    - VM_WARN_ON_ONCE(wp_copy);
    err = shmem_mfill_atomic_pte(dst_mm, dst_pmd, dst_vma,
    dst_addr, src_addr,
    mode != MCOPY_ATOMIC_NORMAL,
    - page);
    + wp_copy, page);
    }

    return err;
    --
    2.32.0
    \
     
     \ /
      Last update: 2022-04-05 04:43    [W:3.426 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site