cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

userfaultfd.c (18981B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *  mm/userfaultfd.c
      4 *
      5 *  Copyright (C) 2015  Red Hat, Inc.
      6 */
      7
      8#include <linux/mm.h>
      9#include <linux/sched/signal.h>
     10#include <linux/pagemap.h>
     11#include <linux/rmap.h>
     12#include <linux/swap.h>
     13#include <linux/swapops.h>
     14#include <linux/userfaultfd_k.h>
     15#include <linux/mmu_notifier.h>
     16#include <linux/hugetlb.h>
     17#include <linux/shmem_fs.h>
     18#include <asm/tlbflush.h>
     19#include <asm/tlb.h>
     20#include "internal.h"
     21
     22static __always_inline
     23struct vm_area_struct *find_dst_vma(struct mm_struct *dst_mm,
     24				    unsigned long dst_start,
     25				    unsigned long len)
     26{
     27	/*
     28	 * Make sure that the dst range is both valid and fully within a
     29	 * single existing vma.
     30	 */
     31	struct vm_area_struct *dst_vma;
     32
     33	dst_vma = find_vma(dst_mm, dst_start);
     34	if (!dst_vma)
     35		return NULL;
     36
     37	if (dst_start < dst_vma->vm_start ||
     38	    dst_start + len > dst_vma->vm_end)
     39		return NULL;
     40
     41	/*
     42	 * Check the vma is registered in uffd, this is required to
     43	 * enforce the VM_MAYWRITE check done at uffd registration
     44	 * time.
     45	 */
     46	if (!dst_vma->vm_userfaultfd_ctx.ctx)
     47		return NULL;
     48
     49	return dst_vma;
     50}
     51
     52/*
     53 * Install PTEs, to map dst_addr (within dst_vma) to page.
     54 *
     55 * This function handles both MCOPY_ATOMIC_NORMAL and _CONTINUE for both shmem
     56 * and anon, and for both shared and private VMAs.
     57 */
     58int mfill_atomic_install_pte(struct mm_struct *dst_mm, pmd_t *dst_pmd,
     59			     struct vm_area_struct *dst_vma,
     60			     unsigned long dst_addr, struct page *page,
     61			     bool newly_allocated, bool wp_copy)
     62{
     63	int ret;
     64	pte_t _dst_pte, *dst_pte;
     65	bool writable = dst_vma->vm_flags & VM_WRITE;
     66	bool vm_shared = dst_vma->vm_flags & VM_SHARED;
     67	bool page_in_cache = page->mapping;
     68	spinlock_t *ptl;
     69	struct inode *inode;
     70	pgoff_t offset, max_off;
     71
     72	_dst_pte = mk_pte(page, dst_vma->vm_page_prot);
     73	_dst_pte = pte_mkdirty(_dst_pte);
     74	if (page_in_cache && !vm_shared)
     75		writable = false;
     76
     77	/*
     78	 * Always mark a PTE as write-protected when needed, regardless of
     79	 * VM_WRITE, which the user might change.
     80	 */
     81	if (wp_copy) {
     82		_dst_pte = pte_mkuffd_wp(_dst_pte);
     83		writable = false;
     84	}
     85
     86	if (writable)
     87		_dst_pte = pte_mkwrite(_dst_pte);
     88	else
     89		/*
     90		 * We need this to make sure write bit removed; as mk_pte()
     91		 * could return a pte with write bit set.
     92		 */
     93		_dst_pte = pte_wrprotect(_dst_pte);
     94
     95	dst_pte = pte_offset_map_lock(dst_mm, dst_pmd, dst_addr, &ptl);
     96
     97	if (vma_is_shmem(dst_vma)) {
     98		/* serialize against truncate with the page table lock */
     99		inode = dst_vma->vm_file->f_inode;
    100		offset = linear_page_index(dst_vma, dst_addr);
    101		max_off = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE);
    102		ret = -EFAULT;
    103		if (unlikely(offset >= max_off))
    104			goto out_unlock;
    105	}
    106
    107	ret = -EEXIST;
    108	/*
    109	 * We allow to overwrite a pte marker: consider when both MISSING|WP
    110	 * registered, we firstly wr-protect a none pte which has no page cache
    111	 * page backing it, then access the page.
    112	 */
    113	if (!pte_none_mostly(*dst_pte))
    114		goto out_unlock;
    115
    116	if (page_in_cache) {
    117		/* Usually, cache pages are already added to LRU */
    118		if (newly_allocated)
    119			lru_cache_add(page);
    120		page_add_file_rmap(page, dst_vma, false);
    121	} else {
    122		page_add_new_anon_rmap(page, dst_vma, dst_addr);
    123		lru_cache_add_inactive_or_unevictable(page, dst_vma);
    124	}
    125
    126	/*
    127	 * Must happen after rmap, as mm_counter() checks mapping (via
    128	 * PageAnon()), which is set by __page_set_anon_rmap().
    129	 */
    130	inc_mm_counter(dst_mm, mm_counter(page));
    131
    132	set_pte_at(dst_mm, dst_addr, dst_pte, _dst_pte);
    133
    134	/* No need to invalidate - it was non-present before */
    135	update_mmu_cache(dst_vma, dst_addr, dst_pte);
    136	ret = 0;
    137out_unlock:
    138	pte_unmap_unlock(dst_pte, ptl);
    139	return ret;
    140}
    141
    142static int mcopy_atomic_pte(struct mm_struct *dst_mm,
    143			    pmd_t *dst_pmd,
    144			    struct vm_area_struct *dst_vma,
    145			    unsigned long dst_addr,
    146			    unsigned long src_addr,
    147			    struct page **pagep,
    148			    bool wp_copy)
    149{
    150	void *page_kaddr;
    151	int ret;
    152	struct page *page;
    153
    154	if (!*pagep) {
    155		ret = -ENOMEM;
    156		page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, dst_vma, dst_addr);
    157		if (!page)
    158			goto out;
    159
    160		page_kaddr = kmap_atomic(page);
    161		ret = copy_from_user(page_kaddr,
    162				     (const void __user *) src_addr,
    163				     PAGE_SIZE);
    164		kunmap_atomic(page_kaddr);
    165
    166		/* fallback to copy_from_user outside mmap_lock */
    167		if (unlikely(ret)) {
    168			ret = -ENOENT;
    169			*pagep = page;
    170			/* don't free the page */
    171			goto out;
    172		}
    173
    174		flush_dcache_page(page);
    175	} else {
    176		page = *pagep;
    177		*pagep = NULL;
    178	}
    179
    180	/*
    181	 * The memory barrier inside __SetPageUptodate makes sure that
    182	 * preceding stores to the page contents become visible before
    183	 * the set_pte_at() write.
    184	 */
    185	__SetPageUptodate(page);
    186
    187	ret = -ENOMEM;
    188	if (mem_cgroup_charge(page_folio(page), dst_mm, GFP_KERNEL))
    189		goto out_release;
    190
    191	ret = mfill_atomic_install_pte(dst_mm, dst_pmd, dst_vma, dst_addr,
    192				       page, true, wp_copy);
    193	if (ret)
    194		goto out_release;
    195out:
    196	return ret;
    197out_release:
    198	put_page(page);
    199	goto out;
    200}
    201
    202static int mfill_zeropage_pte(struct mm_struct *dst_mm,
    203			      pmd_t *dst_pmd,
    204			      struct vm_area_struct *dst_vma,
    205			      unsigned long dst_addr)
    206{
    207	pte_t _dst_pte, *dst_pte;
    208	spinlock_t *ptl;
    209	int ret;
    210	pgoff_t offset, max_off;
    211	struct inode *inode;
    212
    213	_dst_pte = pte_mkspecial(pfn_pte(my_zero_pfn(dst_addr),
    214					 dst_vma->vm_page_prot));
    215	dst_pte = pte_offset_map_lock(dst_mm, dst_pmd, dst_addr, &ptl);
    216	if (dst_vma->vm_file) {
    217		/* the shmem MAP_PRIVATE case requires checking the i_size */
    218		inode = dst_vma->vm_file->f_inode;
    219		offset = linear_page_index(dst_vma, dst_addr);
    220		max_off = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE);
    221		ret = -EFAULT;
    222		if (unlikely(offset >= max_off))
    223			goto out_unlock;
    224	}
    225	ret = -EEXIST;
    226	if (!pte_none(*dst_pte))
    227		goto out_unlock;
    228	set_pte_at(dst_mm, dst_addr, dst_pte, _dst_pte);
    229	/* No need to invalidate - it was non-present before */
    230	update_mmu_cache(dst_vma, dst_addr, dst_pte);
    231	ret = 0;
    232out_unlock:
    233	pte_unmap_unlock(dst_pte, ptl);
    234	return ret;
    235}
    236
    237/* Handles UFFDIO_CONTINUE for all shmem VMAs (shared or private). */
    238static int mcontinue_atomic_pte(struct mm_struct *dst_mm,
    239				pmd_t *dst_pmd,
    240				struct vm_area_struct *dst_vma,
    241				unsigned long dst_addr,
    242				bool wp_copy)
    243{
    244	struct inode *inode = file_inode(dst_vma->vm_file);
    245	pgoff_t pgoff = linear_page_index(dst_vma, dst_addr);
    246	struct page *page;
    247	int ret;
    248
    249	ret = shmem_getpage(inode, pgoff, &page, SGP_READ);
    250	if (ret)
    251		goto out;
    252	if (!page) {
    253		ret = -EFAULT;
    254		goto out;
    255	}
    256
    257	if (PageHWPoison(page)) {
    258		ret = -EIO;
    259		goto out_release;
    260	}
    261
    262	ret = mfill_atomic_install_pte(dst_mm, dst_pmd, dst_vma, dst_addr,
    263				       page, false, wp_copy);
    264	if (ret)
    265		goto out_release;
    266
    267	unlock_page(page);
    268	ret = 0;
    269out:
    270	return ret;
    271out_release:
    272	unlock_page(page);
    273	put_page(page);
    274	goto out;
    275}
    276
    277static pmd_t *mm_alloc_pmd(struct mm_struct *mm, unsigned long address)
    278{
    279	pgd_t *pgd;
    280	p4d_t *p4d;
    281	pud_t *pud;
    282
    283	pgd = pgd_offset(mm, address);
    284	p4d = p4d_alloc(mm, pgd, address);
    285	if (!p4d)
    286		return NULL;
    287	pud = pud_alloc(mm, p4d, address);
    288	if (!pud)
    289		return NULL;
    290	/*
    291	 * Note that we didn't run this because the pmd was
    292	 * missing, the *pmd may be already established and in
    293	 * turn it may also be a trans_huge_pmd.
    294	 */
    295	return pmd_alloc(mm, pud, address);
    296}
    297
    298#ifdef CONFIG_HUGETLB_PAGE
    299/*
    300 * __mcopy_atomic processing for HUGETLB vmas.  Note that this routine is
    301 * called with mmap_lock held, it will release mmap_lock before returning.
    302 */
    303static __always_inline ssize_t __mcopy_atomic_hugetlb(struct mm_struct *dst_mm,
    304					      struct vm_area_struct *dst_vma,
    305					      unsigned long dst_start,
    306					      unsigned long src_start,
    307					      unsigned long len,
    308					      enum mcopy_atomic_mode mode,
    309					      bool wp_copy)
    310{
    311	int vm_shared = dst_vma->vm_flags & VM_SHARED;
    312	ssize_t err;
    313	pte_t *dst_pte;
    314	unsigned long src_addr, dst_addr;
    315	long copied;
    316	struct page *page;
    317	unsigned long vma_hpagesize;
    318	pgoff_t idx;
    319	u32 hash;
    320	struct address_space *mapping;
    321
    322	/*
    323	 * There is no default zero huge page for all huge page sizes as
    324	 * supported by hugetlb.  A PMD_SIZE huge pages may exist as used
    325	 * by THP.  Since we can not reliably insert a zero page, this
    326	 * feature is not supported.
    327	 */
    328	if (mode == MCOPY_ATOMIC_ZEROPAGE) {
    329		mmap_read_unlock(dst_mm);
    330		return -EINVAL;
    331	}
    332
    333	src_addr = src_start;
    334	dst_addr = dst_start;
    335	copied = 0;
    336	page = NULL;
    337	vma_hpagesize = vma_kernel_pagesize(dst_vma);
    338
    339	/*
    340	 * Validate alignment based on huge page size
    341	 */
    342	err = -EINVAL;
    343	if (dst_start & (vma_hpagesize - 1) || len & (vma_hpagesize - 1))
    344		goto out_unlock;
    345
    346retry:
    347	/*
    348	 * On routine entry dst_vma is set.  If we had to drop mmap_lock and
    349	 * retry, dst_vma will be set to NULL and we must lookup again.
    350	 */
    351	if (!dst_vma) {
    352		err = -ENOENT;
    353		dst_vma = find_dst_vma(dst_mm, dst_start, len);
    354		if (!dst_vma || !is_vm_hugetlb_page(dst_vma))
    355			goto out_unlock;
    356
    357		err = -EINVAL;
    358		if (vma_hpagesize != vma_kernel_pagesize(dst_vma))
    359			goto out_unlock;
    360
    361		vm_shared = dst_vma->vm_flags & VM_SHARED;
    362	}
    363
    364	/*
    365	 * If not shared, ensure the dst_vma has a anon_vma.
    366	 */
    367	err = -ENOMEM;
    368	if (!vm_shared) {
    369		if (unlikely(anon_vma_prepare(dst_vma)))
    370			goto out_unlock;
    371	}
    372
    373	while (src_addr < src_start + len) {
    374		BUG_ON(dst_addr >= dst_start + len);
    375
    376		/*
    377		 * Serialize via i_mmap_rwsem and hugetlb_fault_mutex.
    378		 * i_mmap_rwsem ensures the dst_pte remains valid even
    379		 * in the case of shared pmds.  fault mutex prevents
    380		 * races with other faulting threads.
    381		 */
    382		mapping = dst_vma->vm_file->f_mapping;
    383		i_mmap_lock_read(mapping);
    384		idx = linear_page_index(dst_vma, dst_addr);
    385		hash = hugetlb_fault_mutex_hash(mapping, idx);
    386		mutex_lock(&hugetlb_fault_mutex_table[hash]);
    387
    388		err = -ENOMEM;
    389		dst_pte = huge_pte_alloc(dst_mm, dst_vma, dst_addr, vma_hpagesize);
    390		if (!dst_pte) {
    391			mutex_unlock(&hugetlb_fault_mutex_table[hash]);
    392			i_mmap_unlock_read(mapping);
    393			goto out_unlock;
    394		}
    395
    396		if (mode != MCOPY_ATOMIC_CONTINUE &&
    397		    !huge_pte_none_mostly(huge_ptep_get(dst_pte))) {
    398			err = -EEXIST;
    399			mutex_unlock(&hugetlb_fault_mutex_table[hash]);
    400			i_mmap_unlock_read(mapping);
    401			goto out_unlock;
    402		}
    403
    404		err = hugetlb_mcopy_atomic_pte(dst_mm, dst_pte, dst_vma,
    405					       dst_addr, src_addr, mode, &page,
    406					       wp_copy);
    407
    408		mutex_unlock(&hugetlb_fault_mutex_table[hash]);
    409		i_mmap_unlock_read(mapping);
    410
    411		cond_resched();
    412
    413		if (unlikely(err == -ENOENT)) {
    414			mmap_read_unlock(dst_mm);
    415			BUG_ON(!page);
    416
    417			err = copy_huge_page_from_user(page,
    418						(const void __user *)src_addr,
    419						vma_hpagesize / PAGE_SIZE,
    420						true);
    421			if (unlikely(err)) {
    422				err = -EFAULT;
    423				goto out;
    424			}
    425			mmap_read_lock(dst_mm);
    426
    427			dst_vma = NULL;
    428			goto retry;
    429		} else
    430			BUG_ON(page);
    431
    432		if (!err) {
    433			dst_addr += vma_hpagesize;
    434			src_addr += vma_hpagesize;
    435			copied += vma_hpagesize;
    436
    437			if (fatal_signal_pending(current))
    438				err = -EINTR;
    439		}
    440		if (err)
    441			break;
    442	}
    443
    444out_unlock:
    445	mmap_read_unlock(dst_mm);
    446out:
    447	if (page)
    448		put_page(page);
    449	BUG_ON(copied < 0);
    450	BUG_ON(err > 0);
    451	BUG_ON(!copied && !err);
    452	return copied ? copied : err;
    453}
    454#else /* !CONFIG_HUGETLB_PAGE */
    455/* fail at build time if gcc attempts to use this */
    456extern ssize_t __mcopy_atomic_hugetlb(struct mm_struct *dst_mm,
    457				      struct vm_area_struct *dst_vma,
    458				      unsigned long dst_start,
    459				      unsigned long src_start,
    460				      unsigned long len,
    461				      enum mcopy_atomic_mode mode,
    462				      bool wp_copy);
    463#endif /* CONFIG_HUGETLB_PAGE */
    464
    465static __always_inline ssize_t mfill_atomic_pte(struct mm_struct *dst_mm,
    466						pmd_t *dst_pmd,
    467						struct vm_area_struct *dst_vma,
    468						unsigned long dst_addr,
    469						unsigned long src_addr,
    470						struct page **page,
    471						enum mcopy_atomic_mode mode,
    472						bool wp_copy)
    473{
    474	ssize_t err;
    475
    476	if (mode == MCOPY_ATOMIC_CONTINUE) {
    477		return mcontinue_atomic_pte(dst_mm, dst_pmd, dst_vma, dst_addr,
    478					    wp_copy);
    479	}
    480
    481	/*
    482	 * The normal page fault path for a shmem will invoke the
    483	 * fault, fill the hole in the file and COW it right away. The
    484	 * result generates plain anonymous memory. So when we are
    485	 * asked to fill an hole in a MAP_PRIVATE shmem mapping, we'll
    486	 * generate anonymous memory directly without actually filling
    487	 * the hole. For the MAP_PRIVATE case the robustness check
    488	 * only happens in the pagetable (to verify it's still none)
    489	 * and not in the radix tree.
    490	 */
    491	if (!(dst_vma->vm_flags & VM_SHARED)) {
    492		if (mode == MCOPY_ATOMIC_NORMAL)
    493			err = mcopy_atomic_pte(dst_mm, dst_pmd, dst_vma,
    494					       dst_addr, src_addr, page,
    495					       wp_copy);
    496		else
    497			err = mfill_zeropage_pte(dst_mm, dst_pmd,
    498						 dst_vma, dst_addr);
    499	} else {
    500		err = shmem_mfill_atomic_pte(dst_mm, dst_pmd, dst_vma,
    501					     dst_addr, src_addr,
    502					     mode != MCOPY_ATOMIC_NORMAL,
    503					     wp_copy, page);
    504	}
    505
    506	return err;
    507}
    508
    509static __always_inline ssize_t __mcopy_atomic(struct mm_struct *dst_mm,
    510					      unsigned long dst_start,
    511					      unsigned long src_start,
    512					      unsigned long len,
    513					      enum mcopy_atomic_mode mcopy_mode,
    514					      atomic_t *mmap_changing,
    515					      __u64 mode)
    516{
    517	struct vm_area_struct *dst_vma;
    518	ssize_t err;
    519	pmd_t *dst_pmd;
    520	unsigned long src_addr, dst_addr;
    521	long copied;
    522	struct page *page;
    523	bool wp_copy;
    524
    525	/*
    526	 * Sanitize the command parameters:
    527	 */
    528	BUG_ON(dst_start & ~PAGE_MASK);
    529	BUG_ON(len & ~PAGE_MASK);
    530
    531	/* Does the address range wrap, or is the span zero-sized? */
    532	BUG_ON(src_start + len <= src_start);
    533	BUG_ON(dst_start + len <= dst_start);
    534
    535	src_addr = src_start;
    536	dst_addr = dst_start;
    537	copied = 0;
    538	page = NULL;
    539retry:
    540	mmap_read_lock(dst_mm);
    541
    542	/*
    543	 * If memory mappings are changing because of non-cooperative
    544	 * operation (e.g. mremap) running in parallel, bail out and
    545	 * request the user to retry later
    546	 */
    547	err = -EAGAIN;
    548	if (mmap_changing && atomic_read(mmap_changing))
    549		goto out_unlock;
    550
    551	/*
    552	 * Make sure the vma is not shared, that the dst range is
    553	 * both valid and fully within a single existing vma.
    554	 */
    555	err = -ENOENT;
    556	dst_vma = find_dst_vma(dst_mm, dst_start, len);
    557	if (!dst_vma)
    558		goto out_unlock;
    559
    560	err = -EINVAL;
    561	/*
    562	 * shmem_zero_setup is invoked in mmap for MAP_ANONYMOUS|MAP_SHARED but
    563	 * it will overwrite vm_ops, so vma_is_anonymous must return false.
    564	 */
    565	if (WARN_ON_ONCE(vma_is_anonymous(dst_vma) &&
    566	    dst_vma->vm_flags & VM_SHARED))
    567		goto out_unlock;
    568
    569	/*
    570	 * validate 'mode' now that we know the dst_vma: don't allow
    571	 * a wrprotect copy if the userfaultfd didn't register as WP.
    572	 */
    573	wp_copy = mode & UFFDIO_COPY_MODE_WP;
    574	if (wp_copy && !(dst_vma->vm_flags & VM_UFFD_WP))
    575		goto out_unlock;
    576
    577	/*
    578	 * If this is a HUGETLB vma, pass off to appropriate routine
    579	 */
    580	if (is_vm_hugetlb_page(dst_vma))
    581		return  __mcopy_atomic_hugetlb(dst_mm, dst_vma, dst_start,
    582					       src_start, len, mcopy_mode,
    583					       wp_copy);
    584
    585	if (!vma_is_anonymous(dst_vma) && !vma_is_shmem(dst_vma))
    586		goto out_unlock;
    587	if (!vma_is_shmem(dst_vma) && mcopy_mode == MCOPY_ATOMIC_CONTINUE)
    588		goto out_unlock;
    589
    590	/*
    591	 * Ensure the dst_vma has a anon_vma or this page
    592	 * would get a NULL anon_vma when moved in the
    593	 * dst_vma.
    594	 */
    595	err = -ENOMEM;
    596	if (!(dst_vma->vm_flags & VM_SHARED) &&
    597	    unlikely(anon_vma_prepare(dst_vma)))
    598		goto out_unlock;
    599
    600	while (src_addr < src_start + len) {
    601		pmd_t dst_pmdval;
    602
    603		BUG_ON(dst_addr >= dst_start + len);
    604
    605		dst_pmd = mm_alloc_pmd(dst_mm, dst_addr);
    606		if (unlikely(!dst_pmd)) {
    607			err = -ENOMEM;
    608			break;
    609		}
    610
    611		dst_pmdval = pmd_read_atomic(dst_pmd);
    612		/*
    613		 * If the dst_pmd is mapped as THP don't
    614		 * override it and just be strict.
    615		 */
    616		if (unlikely(pmd_trans_huge(dst_pmdval))) {
    617			err = -EEXIST;
    618			break;
    619		}
    620		if (unlikely(pmd_none(dst_pmdval)) &&
    621		    unlikely(__pte_alloc(dst_mm, dst_pmd))) {
    622			err = -ENOMEM;
    623			break;
    624		}
    625		/* If an huge pmd materialized from under us fail */
    626		if (unlikely(pmd_trans_huge(*dst_pmd))) {
    627			err = -EFAULT;
    628			break;
    629		}
    630
    631		BUG_ON(pmd_none(*dst_pmd));
    632		BUG_ON(pmd_trans_huge(*dst_pmd));
    633
    634		err = mfill_atomic_pte(dst_mm, dst_pmd, dst_vma, dst_addr,
    635				       src_addr, &page, mcopy_mode, wp_copy);
    636		cond_resched();
    637
    638		if (unlikely(err == -ENOENT)) {
    639			void *page_kaddr;
    640
    641			mmap_read_unlock(dst_mm);
    642			BUG_ON(!page);
    643
    644			page_kaddr = kmap(page);
    645			err = copy_from_user(page_kaddr,
    646					     (const void __user *) src_addr,
    647					     PAGE_SIZE);
    648			kunmap(page);
    649			if (unlikely(err)) {
    650				err = -EFAULT;
    651				goto out;
    652			}
    653			flush_dcache_page(page);
    654			goto retry;
    655		} else
    656			BUG_ON(page);
    657
    658		if (!err) {
    659			dst_addr += PAGE_SIZE;
    660			src_addr += PAGE_SIZE;
    661			copied += PAGE_SIZE;
    662
    663			if (fatal_signal_pending(current))
    664				err = -EINTR;
    665		}
    666		if (err)
    667			break;
    668	}
    669
    670out_unlock:
    671	mmap_read_unlock(dst_mm);
    672out:
    673	if (page)
    674		put_page(page);
    675	BUG_ON(copied < 0);
    676	BUG_ON(err > 0);
    677	BUG_ON(!copied && !err);
    678	return copied ? copied : err;
    679}
    680
    681ssize_t mcopy_atomic(struct mm_struct *dst_mm, unsigned long dst_start,
    682		     unsigned long src_start, unsigned long len,
    683		     atomic_t *mmap_changing, __u64 mode)
    684{
    685	return __mcopy_atomic(dst_mm, dst_start, src_start, len,
    686			      MCOPY_ATOMIC_NORMAL, mmap_changing, mode);
    687}
    688
    689ssize_t mfill_zeropage(struct mm_struct *dst_mm, unsigned long start,
    690		       unsigned long len, atomic_t *mmap_changing)
    691{
    692	return __mcopy_atomic(dst_mm, start, 0, len, MCOPY_ATOMIC_ZEROPAGE,
    693			      mmap_changing, 0);
    694}
    695
    696ssize_t mcopy_continue(struct mm_struct *dst_mm, unsigned long start,
    697		       unsigned long len, atomic_t *mmap_changing)
    698{
    699	return __mcopy_atomic(dst_mm, start, 0, len, MCOPY_ATOMIC_CONTINUE,
    700			      mmap_changing, 0);
    701}
    702
    703int mwriteprotect_range(struct mm_struct *dst_mm, unsigned long start,
    704			unsigned long len, bool enable_wp,
    705			atomic_t *mmap_changing)
    706{
    707	struct vm_area_struct *dst_vma;
    708	unsigned long page_mask;
    709	struct mmu_gather tlb;
    710	pgprot_t newprot;
    711	int err;
    712
    713	/*
    714	 * Sanitize the command parameters:
    715	 */
    716	BUG_ON(start & ~PAGE_MASK);
    717	BUG_ON(len & ~PAGE_MASK);
    718
    719	/* Does the address range wrap, or is the span zero-sized? */
    720	BUG_ON(start + len <= start);
    721
    722	mmap_read_lock(dst_mm);
    723
    724	/*
    725	 * If memory mappings are changing because of non-cooperative
    726	 * operation (e.g. mremap) running in parallel, bail out and
    727	 * request the user to retry later
    728	 */
    729	err = -EAGAIN;
    730	if (mmap_changing && atomic_read(mmap_changing))
    731		goto out_unlock;
    732
    733	err = -ENOENT;
    734	dst_vma = find_dst_vma(dst_mm, start, len);
    735
    736	if (!dst_vma)
    737		goto out_unlock;
    738	if (!userfaultfd_wp(dst_vma))
    739		goto out_unlock;
    740	if (!vma_can_userfault(dst_vma, dst_vma->vm_flags))
    741		goto out_unlock;
    742
    743	if (is_vm_hugetlb_page(dst_vma)) {
    744		err = -EINVAL;
    745		page_mask = vma_kernel_pagesize(dst_vma) - 1;
    746		if ((start & page_mask) || (len & page_mask))
    747			goto out_unlock;
    748	}
    749
    750	if (enable_wp)
    751		newprot = vm_get_page_prot(dst_vma->vm_flags & ~(VM_WRITE));
    752	else
    753		newprot = vm_get_page_prot(dst_vma->vm_flags);
    754
    755	tlb_gather_mmu(&tlb, dst_mm);
    756	change_protection(&tlb, dst_vma, start, start + len, newprot,
    757			  enable_wp ? MM_CP_UFFD_WP : MM_CP_UFFD_WP_RESOLVE);
    758	tlb_finish_mmu(&tlb);
    759
    760	err = 0;
    761out_unlock:
    762	mmap_read_unlock(dst_mm);
    763	return err;
    764}