linux/mm
Kiryl Shutsemau (Meta) 2d427bb016 mm/userfaultfd: add RWP fault delivery and expose UFFDIO_REGISTER_MODE_RWP
Wire the fault side of read-write protection tracking and turn the
userspace interface on.

An RWP-protected PTE is PAGE_NONE with the uffd bit set.  The PROT_NONE
triggers a fault on any access; the uffd bit distinguishes it from plain
mprotect(PROT_NONE) or NUMA hinting.

Fault dispatch, per level:

  PTE     handle_pte_fault()    -> do_uffd_rwp()
  PMD     __handle_mm_fault()   -> do_huge_pmd_uffd_rwp()
  hugetlb hugetlb_fault()       -> hugetlb_handle_userfault()

The RWP branches gate on userfaultfd_pte_rwp() /
userfaultfd_huge_pmd_rwp() (VM_UFFD_RWP plus the uffd bit) and fall
through to do_numa_page() / do_huge_pmd_numa_page() otherwise.  Each
delivers a UFFD_PAGEFAULT_FLAG_RWP message through handle_userfault(); the
handler resolves it with UFFDIO_RWPROTECT clearing MODE_RWP.

userfaultfd_must_wait() and userfaultfd_huge_must_wait() add matching
protnone+uffd waiters so sync-mode fault handlers block correctly.

Expose the UAPI:

  UFFDIO_REGISTER_MODE_RWP   -> UFFD_API_REGISTER_MODES
  UFFD_FEATURE_RWP           -> UFFD_API_FEATURES
  _UFFDIO_RWPROTECT          -> UFFD_API_RANGE_IOCTLS
                                UFFD_API_RANGE_IOCTLS_BASIC

UFFD_FEATURE_RWP is masked out at UFFDIO_API time when PROT_NONE is not
available or VM_UFFD_RWP aliases VM_NONE (32-bit), so userspace never sees
an advertised-but-broken feature.

Works on anonymous, shmem, and hugetlb memory.

Link: https://lore.kernel.org/20260708111417.173443-11-kirill@shutemov.name
Signed-off-by: Kiryl Shutsemau <kas@kernel.org>
Assisted-by: Claude:claude-opus-4-6
Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: David Hildenbrand <david@kernel.org>
Cc: James Houghton <jthoughton@google.com>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Liam Howlett <liam@infradead.org>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Peter Xu <peterx@redhat.com>
Cc: Sean Christopherson <seanjc@google.com>
Cc: SeongJae Park <sj@kernel.org>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: Zi Yan <ziy@nvidia.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
2026-08-04 19:18:38 -07:00
..
damon mm/damon/core: wait ctx stop in damon_call() before reruning an error 2026-08-04 19:18:31 -07:00
kasan mm/kasan: remove redundant initialization for kasan_flag_write_only 2026-07-28 21:11:44 -07:00
kfence slab changes for 7.2 - part 2 2026-06-22 08:28:48 -07:00
kmsan mm: split out internal page_alloc.h 2026-07-30 19:40:41 -07:00
tests sparc/mm: export symbols for lazy_mmu_mode KUnit tests 2026-01-31 14:22:40 -08:00
alloc_tag.c mm: replace __GFP_NO_CODETAG with ALLOC_NO_CODETAG 2026-07-30 19:40:44 -07:00
backing-dev.c mm: blk-cgroup: fix use-after-free in cgwb_release_workfn() 2026-04-18 23:24:27 -07:00
balloon.c mm: rename CONFIG_BALLOON_COMPACTION to CONFIG_BALLOON_MIGRATION 2026-01-31 14:22:36 -08:00
bootmem_info.c mm/bootmem_info: stop marking mem_section_usage as MIX_SECTION_INFO 2026-06-02 15:22:11 -07:00
bpf_memcontrol.c
cma_debug.c mm/cma_debug: fix invalid accesses for inactive CMA areas 2026-05-28 20:50:33 -07:00
cma_sysfs.c mm/cma_sysfs: skip inactive CMA areas in sysfs 2026-06-03 16:25:49 -07:00
cma.c mm/hugetlb_cma: validate hugetlb CMA range by zone at reserve time 2026-07-28 21:11:59 -07:00
cma.h
compaction.c mm/compaction: stop recording free page order in page->private 2026-08-04 19:18:32 -07:00
debug_page_alloc.c
debug_page_ref.c
debug_vm_pgtable.c mm: decouple protnone helpers from CONFIG_NUMA_BALANCING 2026-08-04 19:18:36 -07:00
debug.c
dmapool_test.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
dmapool.c
early_ioremap.c mm/early_ioremap: clean up the use of WARN() for debugging 2026-01-26 20:02:26 -08:00
execmem.c mm/execmem: make the populate and alloc atomic 2026-04-05 13:53:34 -07:00
fadvise.c mm/fadvise: validate offset in generic_fadvise 2026-04-05 13:52:53 -07:00
fail_page_alloc.c
failslab.c
filemap.c mm: fix mapping_seek_hole_data() overflow on last page 2026-07-30 19:40:37 -07:00
folio-compat.c mm: add SPDX id lines to some mm source files 2026-02-06 15:47:16 -08:00
folio.c mm: rename swap.c to folio.c 2026-08-04 19:18:35 -07:00
gup_test.c mm/gup_test: reject wrapped user ranges 2026-06-21 11:37:37 -07:00
gup_test.h
gup.c mm/gup: cleanup pgtable entry accessors 2026-05-28 21:04:41 -07:00
highmem.c mm/highmem: fix __kmap_to_page() build error 2026-01-31 14:22:38 -08:00
hmm.c mm: rename ARCH_ENABLE_THP_MIGRATION to ARCH_HAS_PMD_SOFTLEAVES 2026-07-30 19:40:25 -07:00
huge_memory.c mm/userfaultfd: add RWP fault delivery and expose UFFDIO_REGISTER_MODE_RWP 2026-08-04 19:18:38 -07:00
hugetlb_cgroup.c Convert 'alloc_flex' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
hugetlb_cma.c mm/hugetlb: remove unused bootmem cma field 2026-07-28 21:12:00 -07:00
hugetlb_cma.h mm/hugetlb: refactor early boot gigantic hugepage allocation 2026-07-28 21:11:59 -07:00
hugetlb_internal.h
hugetlb_sysctl.c
hugetlb_sysfs.c
hugetlb_vmemmap.c mm/hugetlb: avoid unnecessary TLB flush for empty folio list in vmemmap optimize 2026-07-30 19:40:28 -07:00
hugetlb_vmemmap.h mm/sparse-vmemmap: remove sparse_vmemmap_init_nid_late() 2026-07-28 21:12:00 -07:00
hugetlb.c mm/userfaultfd: add RWP fault delivery and expose UFFDIO_REGISTER_MODE_RWP 2026-08-04 19:18:38 -07:00
hwpoison-inject.c
init-mm.c exec_state: relocate dumpable information 2026-05-26 11:02:01 +02:00
internal.h mm: rename uffd-wp PTE accessors to uffd 2026-08-04 19:18:36 -07:00
interval_tree.c mm/memory: simplify calculation in unmap_mapping_range_tree() 2026-04-05 13:53:13 -07:00
ioremap.c
Kconfig userfaultfd: add UFFDIO_REGISTER_MODE_RWP and UFFDIO_RWPROTECT plumbing 2026-08-04 19:18:38 -07:00
Kconfig.debug mm: move alloc tag to mm 2026-07-28 21:12:03 -07:00
khugepaged.c mm: handle VM_UFFD_RWP in khugepaged, rmap, and GUP 2026-08-04 19:18:38 -07:00
kmemleak.c mm/kmemleak: skip the remaining scan phases when interrupted 2026-07-28 21:12:01 -07:00
ksm.c mm: remove PageTransCompound() 2026-07-28 21:11:47 -07:00
list_lru.c mm.git review status for mm-hotfixes-stable..mm-stable 2026-06-19 10:14:34 -07:00
maccess.c
madvise.c mm: cleanup clear_not_present_full_ptes() and rename to clear_non_present_ptes() 2026-07-28 21:12:10 -07:00
Makefile mm: rename swap.c to folio.c 2026-08-04 19:18:35 -07:00
mapping_dirty_helpers.c
memblock.c kho: fix deferred initialization of scratch areas 2026-06-01 02:31:37 +03:00
memcontrol-v1.c memcg-v1: bail out reclaim when memcg is dying 2026-08-04 19:18:27 -07:00
memcontrol-v1.h Merge branch 'mm-hotfixes-stable' into mm-stable in order to pick up 2026-08-04 19:15:12 -07:00
memcontrol.c memcg: bail out memory.max when memcg is dying 2026-08-04 19:18:26 -07:00
memfd_luo.c mm/memfd_luo: document preservation of file seals 2026-05-04 14:03:16 +00:00
memfd.c mm: move reclaim-internal declarations out of swap.h 2026-08-04 19:18:35 -07:00
memory_hotplug.c mm: split out internal page_alloc.h 2026-07-30 19:40:41 -07:00
memory-failure.c mm/memory-failure: add panic option for unrecoverable pages 2026-08-04 19:18:28 -07:00
memory-tiers.c mm: introduce CONFIG_NUMA_MIGRATION and simplify CONFIG_MIGRATION 2026-04-05 13:53:33 -07:00
memory.c mm/userfaultfd: add RWP fault delivery and expose UFFDIO_REGISTER_MODE_RWP 2026-08-04 19:18:38 -07:00
mempolicy.c mm/page_alloc: unify __alloc_frozen_pages[_nolock]_noprof() 2026-07-30 19:40:41 -07:00
mempool.c mm: simplify the mempool_alloc_bulk API 2026-06-03 18:20:47 +02:00
memremap.c mm: decrement MTHP_STAT_NR_ANON in free_zone_device_folio() 2026-07-28 17:37:31 -07:00
memtest.c
migrate_device.c mm: rename uffd-wp PTE accessors to uffd 2026-08-04 19:18:36 -07:00
migrate.c mm: preserve RWP marker across PTE rewrites 2026-08-04 19:18:37 -07:00
mincore.c mm: mincore: use walk_page_range_vma() in do_mincore() 2026-07-28 21:11:52 -07:00
mlock.c mm: mlock: use walk_page_range_vma() in mlock_vma_pages_range() 2026-07-28 21:11:52 -07:00
mm_init.c mm: split out internal page_alloc.h 2026-07-30 19:40:41 -07:00
mm_slot.h
mmap_lock.c mm/vma: improve and document __is_vma_write_locked() 2026-01-31 14:22:51 -08:00
mmap.c mm: fix mmap errno value when MAP_DROPPABLE is not supported 2026-05-28 21:04:48 -07:00
mmu_gather.c mm/mmu_gather: replace IPI with synchronize_rcu() when batch allocation fails 2026-04-05 13:53:05 -07:00
mmu_notifier.c mm.git review status for linus..mm-stable 2026-04-15 12:59:16 -07:00
mmzone.c mm: constify oom_control, scan_control, and alloc_context nodemask 2026-07-28 21:12:04 -07:00
mprotect.c mm: preserve RWP marker across PTE rewrites 2026-08-04 19:18:37 -07:00
mremap.c mm: preserve RWP marker across PTE rewrites 2026-08-04 19:18:37 -07:00
mseal.c mm/mseal: use min/max in mseal_apply 2026-06-02 15:22:15 -07:00
msync.c
nommu.c mm: nommu: add sysctl_max_map_count() check for do_mmap() 2026-07-30 19:40:49 -07:00
numa_emulation.c mm/fake-numa: fix under-allocation detection in uniform split 2026-06-02 08:34:03 +03:00
numa_memblks.c memblock: numa_memblks: fix detection of NUMA node for CXL windows 2026-02-21 09:58:22 -08:00
numa.c
oom_kill.c mm/oom_kill.c: simpilfy rcu call with guard(rcu) 2026-04-05 13:53:17 -07:00
page_alloc.c mm/page_alloc: make sure tail_page->private is zero at page free time 2026-08-04 19:18:33 -07:00
page_alloc.h mm: replace __GFP_NO_CODETAG with ALLOC_NO_CODETAG 2026-07-30 19:40:44 -07:00
page_counter.c
page_ext.c
page_frag_cache.c mm: replace __GFP_NO_CODETAG with ALLOC_NO_CODETAG 2026-07-30 19:40:44 -07:00
page_idle.c mm/page_idle.c: remove redundant mmu notifier in aging code 2026-04-05 13:53:02 -07:00
page_io.c block-7.2-20260625 2026-06-25 09:56:47 -07:00
page_isolation.c mm: split out internal page_alloc.h 2026-07-30 19:40:41 -07:00
page_owner.c mm: split out internal page_alloc.h 2026-07-30 19:40:41 -07:00
page_poison.c
page_reporting.c Merge branch 'mm-hotfixes-stable' into mm-stable in order to pick up 2026-08-04 19:15:12 -07:00
page_reporting.h
page_table_check.c mm: rename uffd-wp PTE accessors to uffd 2026-08-04 19:18:36 -07:00
page_vma_mapped.c mm/page_vma_mapped: use huge_ptep_get() for hugetlb 2026-07-30 19:40:45 -07:00
page-writeback.c vfs-7.2-rc1.writeback 2026-06-15 03:30:45 +05:30
pagewalk.c mm/pagewalk: fix race between concurrent split and refault 2026-04-05 13:53:37 -07:00
percpu-internal.h mm/percpu-internal.h: optimise pcpu_chunk struct to save memory 2026-06-02 15:22:13 -07:00
percpu-km.c mm/percpu-km: clear page->private before free them 2026-08-04 19:18:32 -07:00
percpu-stats.c
percpu-vm.c mm/percpu: make cached pages lookup explicit 2026-07-28 21:11:47 -07:00
percpu.c mm/percpu: avoid IO/FS reclaim in backing allocations 2026-07-28 21:11:47 -07:00
pgalloc-track.h
pgtable-generic.c mm: change to return bool for pmdp_clear_flush_young() 2026-04-05 13:53:35 -07:00
process_vm_access.c
ptdump.c
readahead.c Revert "mm: limit filemap_fault readahead to VMA boundaries" 2026-06-21 11:37:38 -07:00
rmap.c mm: handle VM_UFFD_RWP in khugepaged, rmap, and GUP 2026-08-04 19:18:38 -07:00
rodata_test.c
secretmem.c libfs: drop redundant SB_I_NOEXEC/SB_I_NODEV in init_pseudo() callers 2026-06-04 10:10:49 +02:00
shmem_quota.c treewide: Replace kmalloc with kmalloc_obj for non-scalar types 2026-02-21 01:02:28 -08:00
shmem.c mm/shmem: annotate benign data-race in shmem_getattr() 2026-08-04 19:18:35 -07:00
show_mem.c mm: split out internal page_alloc.h 2026-07-30 19:40:41 -07:00
shrinker_debug.c mm: shrinker: fix NULL pointer dereference in debugfs 2026-07-01 19:02:52 -07:00
shrinker.c mm: shrinker: fix shrinker_info teardown race with expansion 2026-07-01 19:02:52 -07:00
shuffle.c mm: split out internal page_alloc.h 2026-07-30 19:40:41 -07:00
shuffle.h
slab_common.c mm/slab: prevent unbounded recursion in free path with new kmalloc type 2026-07-14 17:22:40 +02:00
slab.h mm: fix ASSERT_EXCLUSIVE_BITS by passing memdesc_flags_t by pointer 2026-07-30 19:40:31 -07:00
slub.c mm: factor out can_spin_trylock() 2026-07-30 19:40:44 -07:00
sparse-vmemmap.c mm/sparse-vmemmap: remove sparse_vmemmap_init_nid_late() 2026-07-28 21:12:00 -07:00
sparse.c mm: fix ASSERT_EXCLUSIVE_BITS by passing memdesc_flags_t by pointer 2026-07-30 19:40:31 -07:00
swap_state.c mm/swap: colocate page-cluster sysctl with swap readahead 2026-08-04 19:18:34 -07:00
swap_table.h mm, swap: merge zeromap into swap table 2026-06-02 15:22:23 -07:00
swap.h mm/swap: colocate page-cluster sysctl with swap readahead 2026-08-04 19:18:34 -07:00
swapfile.c mm: preserve RWP marker across PTE rewrites 2026-08-04 19:18:37 -07:00
truncate.c mm/truncate: use folio_split() in truncate_inode_partial_folio() 2026-06-21 11:37:16 -07:00
usercopy.c
userfaultfd.c mm/userfaultfd: add RWP fault delivery and expose UFFDIO_REGISTER_MODE_RWP 2026-08-04 19:18:38 -07:00
util.c mm/util: don't read __page_2 for order-1 folios in snapshot_page() 2026-07-20 17:41:27 -07:00
vma_exec.c mm: convert do_brk_flags() to use vma_flags_t 2026-04-05 13:53:40 -07:00
vma_init.c
vma_internal.h mm: relocate the page table ceiling and floor definitions 2026-02-12 15:42:53 -08:00
vma.c drivers/char/mem: eliminate unnecessary use of success_hook 2026-06-04 14:44:59 -07:00
vma.h mm: allow handling of stacked mmap_prepare hooks in more drivers 2026-04-05 13:53:44 -07:00
vmalloc.c mm/vmalloc: add alignment info in warning print as possible failure reason 2026-07-30 19:40:39 -07:00
vmpressure.c mm/vmpressure: move v1 userspace eventfd code into memcontrol-v1.c 2026-07-30 19:40:28 -07:00
vmscan.c mm/swap: colocate page-cluster sysctl with swap readahead 2026-08-04 19:18:34 -07:00
vmstat.c mm: move some stuff to mm/page_alloc.h 2026-07-30 19:40:41 -07:00
workingset.c mm/mglru: use folio_mark_accessed to replace folio_set_active 2026-06-04 14:45:02 -07:00
zpdesc.h
zsmalloc.c mm/zsmalloc: document free_zspage helper variants 2026-07-28 21:12:03 -07:00
zswap.c mm, swap: add support for stable large allocation in swap cache directly 2026-06-02 15:22:21 -07:00